Package org.fluxtream.core.connectors.fluxtream_capture

Source Code of org.fluxtream.core.connectors.fluxtream_capture.FluxtreamCapturePhoto

package org.fluxtream.core.connectors.fluxtream_capture;

import java.awt.Dimension;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import com.drew.imaging.ImageProcessingException;
import org.fluxtream.core.connectors.Connector;
import org.fluxtream.core.domain.Geolocation;
import org.fluxtream.core.images.Image;
import org.fluxtream.core.images.ImageOrientation;
import org.fluxtream.core.images.ImageType;
import org.fluxtream.core.utils.HashUtils;
import org.fluxtream.core.utils.ImageUtils;
import org.fluxtream.core.aspects.FlxLogger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

/**
* @author Chris Bartley (bartley@cmu.edu)
*/
public final class FluxtreamCapturePhoto {

    private static final FlxLogger logger = FlxLogger.getLogger(FluxtreamCapturePhoto.class);

    public static class PhotoUploadMetadata {
        private double capture_time_secs_utc = -1;
        @Nullable
        private String comment;
        @Nullable
        private String tags;

        public boolean isValid() {
            return capture_time_secs_utc >= 0;
        }

        public long getCaptureTimeMillisUtc() {
            // convert the capture time from seconds to milliseconds
            return (long)(capture_time_secs_utc * 1000);
        }

        public double getCaptureTimeSecsUtc() {
            return capture_time_secs_utc;
        }

        @Nullable
        public String getComment() {
            return comment;
        }

        @Nullable
        public String getTags() {
            return tags;
        }
    }

    private static final int THUMBNAIL_0_MAX_SIDE_LENGTH_IN_PIXELS = 150;
    private static final int THUMBNAIL_1_MAX_SIDE_LENGTH_IN_PIXELS = 300;
    private static final int THUMBNAIL_2_MAX_SIDE_LENGTH_IN_PIXELS = 500;
    private static final String KEY_VALUE_STORE_KEY_PART_DELIMITER = ".";
    private static final String KEY_VALUE_STORE_FILENAME_PART_DELIMITER = "_";
    private static final String CONNECTOR_PRETTY_NAME = Connector.getConnector("fluxtream_capture").prettyName();
    private static final String OBJECT_TYPE_NAME = "photo";

    @NotNull
    public static String createPhotoStoreKey(final long guestId, @NotNull final String captureYYYYDDD, final long captureTimeMillisUtc, @NotNull final String photoHash) {
        return guestId + KEY_VALUE_STORE_KEY_PART_DELIMITER +
               CONNECTOR_PRETTY_NAME + KEY_VALUE_STORE_KEY_PART_DELIMITER +
               OBJECT_TYPE_NAME + KEY_VALUE_STORE_KEY_PART_DELIMITER +
               captureYYYYDDD + KEY_VALUE_STORE_KEY_PART_DELIMITER +
               captureTimeMillisUtc + KEY_VALUE_STORE_FILENAME_PART_DELIMITER +
               photoHash;
    }

    private final long guestId;

    @NotNull
    private final byte[] photoBytes;

    private final long captureTimeMillisUtc;

    @NotNull
    private final String captureYYYYDDD;

    @NotNull
    private final String photoHash;

    @NotNull
    private final String photoStoreKey;

    @NotNull
    private final byte[] thumbnail0;

    @NotNull
    private final byte[] thumbnail1;

    @NotNull
    private final byte[] thumbnail2;

    @NotNull
    private final Dimension thumbnail0Size;

    @NotNull
    private final Dimension thumbnail1Size;

    @NotNull
    private final Dimension thumbnail2Size;

    @NotNull
    private final ImageOrientation orientation;

    @NotNull
    private final ImageType imageType;

    @Nullable
    private final Geolocation geolocation;

    @Nullable
    private final String tags;

    @Nullable
    private final String comment;

    FluxtreamCapturePhoto(final long guestId, @NotNull final byte[] photoBytes, @NotNull final PhotoUploadMetadata photoUploadMetadata) throws IllegalArgumentException, NoSuchAlgorithmException, IOException, FluxtreamCapturePhotoStore.UnsupportedImageFormatException {

        // Get the image type.  If this is null, then it's not a supported type.
        final ImageType tempImageType = ImageUtils.getImageType(photoBytes);
        if (tempImageType == null) {
            throw new FluxtreamCapturePhotoStore.UnsupportedImageFormatException("The photoBytes do not contain a supported image format");
        }
        imageType = tempImageType;

        if (photoUploadMetadata.getCaptureTimeSecsUtc() < 0) {
            throw new IllegalArgumentException("The captureTimeMillisUtc must be non-negative");
        }

        this.guestId = guestId;
        this.photoBytes = photoBytes;
        this.captureTimeMillisUtc = photoUploadMetadata.getCaptureTimeMillisUtc();
        this.tags = photoUploadMetadata.getTags();
        this.comment = photoUploadMetadata.getComment();

        final DateTime captureTime = new DateTime(captureTimeMillisUtc, DateTimeZone.UTC);
        final String year = String.valueOf(captureTime.getYear());
        final String dayOfYear = String.format("%03d", captureTime.getDayOfYear()); // pad with zeros so that it's always 3 characters
        captureYYYYDDD = year + dayOfYear;
        this.photoHash = HashUtils.computeSha256Hash(photoBytes);
        photoStoreKey = createPhotoStoreKey(guestId, captureYYYYDDD, captureTimeMillisUtc, photoHash);

        // Create the thumbnails: do so by creating the largest one first, and then creating the smaller
        // ones from the larger--this should be faster than creating each from the original image
        final Image thumbnail2Image = ImageUtils.createJpegThumbnail(photoBytes, THUMBNAIL_2_MAX_SIDE_LENGTH_IN_PIXELS);
        if (thumbnail2Image == null) {
            throw new IOException("Failed to create thumbnails");
        }

        final Image thumbnail1Image = ImageUtils.createJpegThumbnail(thumbnail2Image.getBytes(), THUMBNAIL_1_MAX_SIDE_LENGTH_IN_PIXELS);
        if (thumbnail1Image == null) {
            throw new IOException("Failed to create thumbnails");
        }

        final Image thumbnail0Image = ImageUtils.createJpegThumbnail(thumbnail1Image.getBytes(), THUMBNAIL_0_MAX_SIDE_LENGTH_IN_PIXELS);
        if (thumbnail0Image == null) {
            throw new IOException("Failed to create thumbnails");
        }

        thumbnail0 = thumbnail0Image.getBytes();
        thumbnail1 = thumbnail1Image.getBytes();
        thumbnail2 = thumbnail2Image.getBytes();

        thumbnail0Size = new Dimension(thumbnail0Image.getWidth(), thumbnail0Image.getHeight());
        thumbnail1Size = new Dimension(thumbnail1Image.getWidth(), thumbnail1Image.getHeight());
        thumbnail2Size = new Dimension(thumbnail2Image.getWidth(), thumbnail2Image.getHeight());

        // get the image orientation, and default to ORIENTATION_1 if unspecified
        ImageOrientation orientationTemp;
        try {
            orientationTemp = ImageUtils.getOrientation(photoBytes);
        }
        catch (Exception e) {
            logger.error("Exception while trying to read the orientation data for user [" + guestId + "] photo [" + photoStoreKey + "]");
            orientationTemp = null;
        }
        orientation = (orientationTemp == null) ? ImageOrientation.ORIENTATION_1 : orientationTemp;

        Geolocation geolocationTemp;
        try {
            geolocationTemp = ImageUtils.getGeolocation(photoBytes);
        }
        catch (ImageProcessingException e) {
            logger.error("ImageProcessingException while trying to read the geolocation data for user [" + guestId + "] photo [" + photoStoreKey + "]");
            geolocationTemp = null;
        }
        geolocation = geolocationTemp;
    }

    public long getGuestId() {
        return guestId;
    }

    @NotNull
    public byte[] getPhotoBytes() {
        return photoBytes;
    }

    @NotNull
    public String getPhotoHash() {
        return photoHash;
    }

    public long getCaptureTimeMillisUtc() {
        return captureTimeMillisUtc;
    }

    @NotNull
    public String getCaptureYYYYDDD() {
        return captureYYYYDDD;
    }

    @NotNull
    public String getPhotoStoreKey() {
        return photoStoreKey;
    }

    @NotNull
    public byte[] getThumbnail0() {
        return thumbnail0;
    }

    @NotNull
    public byte[] getThumbnail1() {
        return thumbnail1;
    }

    @NotNull
    public byte[] getThumbnail2() {
        return thumbnail2;
    }

    @NotNull
    public Dimension getThumbnail0Size() {
        return thumbnail0Size;
    }

    @NotNull
    public Dimension getThumbnail1Size() {
        return thumbnail1Size;
    }

    @NotNull
    public Dimension getThumbnail2Size() {
        return thumbnail2Size;
    }

    @NotNull
    public ImageOrientation getOrientation() {
        return orientation;
    }

    @NotNull
    public ImageType getImageType() {
        return imageType;
    }

    @Nullable
    public Geolocation getGeolocation() {
        return geolocation;
    }

    @Nullable
    public String getTags() {
        return tags;
    }

    @Nullable
    public String getComment() {
        return comment;
    }
}
TOP

Related Classes of org.fluxtream.core.connectors.fluxtream_capture.FluxtreamCapturePhoto

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.