jodtemplate.pptx.ImageService.java Source code

Java tutorial

Introduction

Here is the source code for jodtemplate.pptx.ImageService.java

Source

/*
 * 
 * Copyright 2015 Andrey Yakovlev
 * 
 * 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.
 * 
 */
package jodtemplate.pptx;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;

import jodtemplate.Image;
import jodtemplate.Relationship;
import jodtemplate.exception.JODTemplateException;
import jodtemplate.image.ImageField;
import jodtemplate.image.ImageMetadataExtractor;
import jodtemplate.resource.Resource;
import jodtemplate.resource.Resources;
import jodtemplate.util.Utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.jdom2.Attribute;
import org.jdom2.DataConversionException;
import org.jdom2.Element;
import org.jdom2.Namespace;

public class ImageService {

    public void insertImage(final ImageField imageField, final Slide slide, final Resources resources,
            final Element pic) throws JODTemplateException {
        try {
            final InputStream is = imageField.getInputStream();
            if (is != null) {
                try (final InputStream bis = new BufferedInputStream(is)) {

                    final byte[] imageContents = IOUtils.toByteArray(bis);

                    final Image image = getImage(imageContents, slide.getPresentation(), resources);

                    final Relationship imageRel = getImageRelationship(image, slide);

                    final Attribute embed = pic
                            .getChild(PPTXDocument.BLIPFILL_ELEMENT, getPresentationmlNamespace())
                            .getChild(PPTXDocument.BLIP_ELEMENT, getDrawingmlNamespace())
                            .getAttribute(PPTXDocument.EMBED_ATTR, getRelationshipsNamespace());
                    embed.setValue(imageRel.getId());

                    setPicSize(pic, image);
                }
            } else {
                pic.getParent().removeContent(pic);
            }
        } catch (IOException | DataConversionException e) {
            throw new JODTemplateException(e);
        }
    }

    private Relationship getImageRelationship(final Image image, final Slide slide) {
        final Path imageFullPath = Paths.get(image.getFullPath());
        final Path slideFullPath = Paths.get(FilenameUtils
                .getFullPath(slide.getPresentation().getFullPath() + slide.getRelationship().getTarget()));
        final Path relativeImagePath = slideFullPath.relativize(imageFullPath);
        final String normRelativeImagePath = FilenameUtils.separatorsToUnix(relativeImagePath.toString());

        Relationship imageRel = slide.getRelationshipByTarget(normRelativeImagePath);

        if (imageRel == null) {
            imageRel = new Relationship();
            imageRel.setId(slide.getNextId());
            imageRel.setTarget(normRelativeImagePath);
            imageRel.setType(Relationship.IMAGE_TYPE);
            slide.addOtherRelationship(imageRel);
        }

        return imageRel;
    }

    private Image getImage(final byte[] imageContents, final Presentation presentation, final Resources resources)
            throws IOException {
        final Image image;
        final String md5 = DigestUtils.md5Hex(imageContents);
        if (presentation.containsImage(md5)) {
            image = presentation.getImage(md5);
        } else {
            image = new Image();
            image.setMd5(md5);

            final ImageMetadataExtractor simpleImageInfo = new ImageMetadataExtractor(imageContents);
            image.setWidth(simpleImageInfo.getWidth());
            image.setHeight(simpleImageInfo.getHeight());
            image.setExtension(simpleImageInfo.getMimeType());

            final int imageIndex = presentation.getNumberOfImages() + 1;
            image.setFullPath(
                    presentation.getFullPath() + "media/imageJodT" + imageIndex + "." + image.getExtension());

            presentation.addImage(image);

            final Resource imageResource = resources
                    .createResource(Utils.removePrefixSeparator(image.getFullPath()));

            try (final OutputStream resOutput = imageResource.getOutputStream()) {
                IOUtils.write(imageContents, resOutput);
            }
        }
        return image;
    }

    private ImageSize calculateNewImageSize(final int cx, final int cy, final int w, final int h) {
        final double cRatio = cx / (double) cy;
        final double ratio = w / (double) h;
        int resX;
        int resY;
        if (w == h) {
            resX = Math.min(cx, cy);
            resY = Math.min(cx, cy);
        } else {
            if (cRatio > ratio) {
                resY = cy;
                resX = (int) (cy * ratio);
            } else {
                resX = cx;
                resY = (int) (cx / ratio);
            }
        }
        return new ImageSize(resX, resY);
    }

    private void setPicSize(final Element pic, final Image image) throws DataConversionException {
        final Element ext = pic.getChild(PPTXDocument.SPPR_ELEMENT, getPresentationmlNamespace())
                .getChild(PPTXDocument.XFRM_ELEMENT, getDrawingmlNamespace())
                .getChild(PPTXDocument.EXT_ELEMENT, getDrawingmlNamespace());

        final Attribute cxAttr = ext.getAttribute("cx");
        final Attribute cyAttr = ext.getAttribute("cy");
        final int cx = cxAttr.getIntValue();
        final int cy = cyAttr.getIntValue();

        final ImageSize newSize = calculateNewImageSize(cx, cy, image.getWidth(), image.getHeight());
        cxAttr.setValue(String.valueOf(newSize.width));
        cyAttr.setValue(String.valueOf(newSize.height));
    }

    private Namespace getDrawingmlNamespace() {
        return Namespace.getNamespace(PPTXDocument.DRAWINGML_NAMESPACE);
    }

    private Namespace getPresentationmlNamespace() {
        return Namespace.getNamespace(PPTXDocument.PRESENTATIONML_NAMESPACE);
    }

    private Namespace getRelationshipsNamespace() {
        return Namespace.getNamespace(PPTXDocument.RELATIONSHIPS_NAMESPACE);
    }

    private static final class ImageSize {
        private int width;

        private int height;

        private ImageSize(final int width, final int height) {
            this.width = width;
            this.height = height;
        }
    }
}