pl.datamatica.traccar.api.providers.ImageProvider.java Source code

Java tutorial

Introduction

Here is the source code for pl.datamatica.traccar.api.providers.ImageProvider.java

Source

/*
 *  Copyright (C) 2016  Datamatica (dev@datamatica.pl)
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published
 *  by the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program 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 Affero General Public License for more details.
 * 
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package pl.datamatica.traccar.api.providers;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.imageio.ImageIO;
import javax.persistence.EntityManager;
import org.apache.commons.io.IOUtils;
import pl.datamatica.traccar.model.Picture;

public class ImageProvider {

    private final File rootDirectory;
    private final EntityManager em;
    private static Image emptyMarker;
    private static final Map<String, byte[]> markerCache = new ConcurrentHashMap<>();
    private static final Map<Long, byte[]> custMarkerCache = new ConcurrentHashMap<>();

    public ImageProvider(String rootDirectory, EntityManager em) {
        this.rootDirectory = new File(rootDirectory);
        this.em = em;
    }

    // TODO: It should have some cache logic.
    public Image getImage(String name) {
        File source = new File(rootDirectory, name);
        try {
            return ImageIO.read(source);
        } catch (IOException ex) {
            System.out.println(ex);
            return null;
        }
    }

    public byte[] getMarker(String name) throws IOException {
        if (!markerCache.containsKey(name)) {
            Image icon = getImage(name + ".png");
            if (icon == null)
                return null;
            float l = 30f / 141, t = 28f / 189, r = 110f / 141, b = 108f / 189;
            int w = emptyMarker.getWidth(null), h = emptyMarker.getHeight(null);
            int tw = (int) Math.round((r - l) * w), th = (int) Math.round((b - t) * h);

            //https://stackoverflow.com/a/7951324
            int wi = icon.getWidth(null), hi = icon.getHeight(null);
            while (wi >= 2 * tw || hi >= 2 * th) {
                if (wi >= 2 * tw)
                    wi /= 2;
                if (hi >= 2 * th)
                    hi /= 2;
                BufferedImage tmp = new BufferedImage(wi, hi, BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2 = tmp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2.drawImage(icon, 0, 0, wi, hi, null);
                g2.dispose();
                icon = tmp;
            }

            BufferedImage marker = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = marker.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(emptyMarker, 0, 0, null);
            g.drawImage(icon, (int) Math.round(l * w), (int) Math.round(t * h), tw, th, null);
            g.dispose();

            ByteArrayOutputStream boss = new ByteArrayOutputStream();
            ImageIO.write((RenderedImage) marker, "png", boss);
            markerCache.put(name, boss.toByteArray());
        }
        return markerCache.get(name);
    }

    public byte[] getCustomMarker(long id) throws IOException {
        if (!custMarkerCache.containsKey(id)) {
            Picture pic = em.find(Picture.class, id);
            if (pic == null)
                return null;
            Image img = ImageIO.read(new ByteArrayInputStream(pic.getData()));
            float l = 17f / 141, t = 15f / 189, r = 123f / 141, b = 120f / 189;
            int w = emptyMarker.getWidth(null), h = emptyMarker.getHeight(null);
            BufferedImage marker = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            marker.createGraphics().drawImage(emptyMarker, 0, 0, null);
            Graphics2D g = marker.createGraphics();
            g.setClip(new Ellipse2D.Float((int) Math.round(l * w), (int) Math.round(t * h),
                    (int) Math.round((r - l) * w), (int) Math.round((b - t) * h)));
            g.drawImage(img, (int) Math.round(l * w), (int) Math.round(t * h), (int) Math.round((r - l) * w),
                    (int) Math.round((b - t) * h), null);

            ByteArrayOutputStream boss = new ByteArrayOutputStream();
            ImageIO.write((RenderedImage) marker, "png", boss);
            custMarkerCache.put(id, boss.toByteArray());
        }
        return custMarkerCache.get(id);
    }

    public byte[] getVecMarker(String name) throws IOException {
        return IOUtils.toByteArray(getInputStreamForVector(name));
    }

    public FileInputStream getInputStreamForImage(String name) {
        try {
            return new FileInputStream(new File(rootDirectory, name + ".png"));
        } catch (FileNotFoundException ex) {
            System.out.println(ex);
            return null;
        }
    }

    public FileInputStream getInputStreamForVector(String name) {
        try {
            return new FileInputStream(new File(rootDirectory, name + ".svg"));
        } catch (FileNotFoundException ex) {
            return null;
        }
    }

    public static final void setEmptyMarker(Image img) {
        emptyMarker = img;
    }
}