Package edu.harvard.hul.ois.fits

Source Code of edu.harvard.hul.ois.fits.MixModel

/**********************************************************************
* Copyright (c) 2009 by the President and Fellows of Harvard College
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Contact information
*
* Office for Information Systems
* Harvard University Library
* Harvard University
* Cambridge, MA  02138
* (617)495-3724
* hulois@hulmail.harvard.edu
**********************************************************************/

package edu.harvard.hul.ois.fits;

import java.util.StringTokenizer;

import edu.harvard.hul.ois.ots.schemas.MIX.BasicDigitalObjectInformation;
import edu.harvard.hul.ois.ots.schemas.MIX.BasicImageCharacteristics;
import edu.harvard.hul.ois.ots.schemas.MIX.BasicImageInformation;
import edu.harvard.hul.ois.ots.schemas.MIX.BitsPerSample;
import edu.harvard.hul.ois.ots.schemas.MIX.CameraCaptureSettings;
import edu.harvard.hul.ois.ots.schemas.MIX.ColorProfile;
import edu.harvard.hul.ois.ots.schemas.MIX.Colormap;
import edu.harvard.hul.ois.ots.schemas.MIX.Component;
import edu.harvard.hul.ois.ots.schemas.MIX.DigitalCameraCapture;
import edu.harvard.hul.ois.ots.schemas.MIX.DigitalCameraModel;
import edu.harvard.hul.ois.ots.schemas.MIX.EncodingOptions;
import edu.harvard.hul.ois.ots.schemas.MIX.GPSData;
import edu.harvard.hul.ois.ots.schemas.MIX.GPSDestLatitude;
import edu.harvard.hul.ois.ots.schemas.MIX.GPSDestLongitude;
import edu.harvard.hul.ois.ots.schemas.MIX.GPSLatitude;
import edu.harvard.hul.ois.ots.schemas.MIX.GPSLongitude;
import edu.harvard.hul.ois.ots.schemas.MIX.GeneralCaptureInformation;
import edu.harvard.hul.ois.ots.schemas.MIX.IccProfile;
import edu.harvard.hul.ois.ots.schemas.MIX.ImageAssessmentMetadata;
import edu.harvard.hul.ois.ots.schemas.MIX.ImageCaptureMetadata;
import edu.harvard.hul.ois.ots.schemas.MIX.ImageColorEncoding;
import edu.harvard.hul.ois.ots.schemas.MIX.ImageData;
import edu.harvard.hul.ois.ots.schemas.MIX.JPEG2000;
import edu.harvard.hul.ois.ots.schemas.MIX.Mix;
import edu.harvard.hul.ois.ots.schemas.MIX.PhotometricInterpretation;
import edu.harvard.hul.ois.ots.schemas.MIX.PrimaryChromaticities;
import edu.harvard.hul.ois.ots.schemas.MIX.ReferenceBlackWhite;
import edu.harvard.hul.ois.ots.schemas.MIX.ScannerCapture;
import edu.harvard.hul.ois.ots.schemas.MIX.ScannerModel;
import edu.harvard.hul.ois.ots.schemas.MIX.ScanningSystemSoftware;
import edu.harvard.hul.ois.ots.schemas.MIX.SpatialMetrics;
import edu.harvard.hul.ois.ots.schemas.MIX.SpecialFormatCharacteristics;
import edu.harvard.hul.ois.ots.schemas.MIX.SubjectDistance;
import edu.harvard.hul.ois.ots.schemas.MIX.Tiles;
import edu.harvard.hul.ois.ots.schemas.MIX.WhitePoint;
import edu.harvard.hul.ois.ots.schemas.MIX.YCbCr;
import edu.harvard.hul.ois.ots.schemas.MIX.YCbCrCoefficients;
import edu.harvard.hul.ois.ots.schemas.MIX.YCbCrSubSampling;
import edu.harvard.hul.ois.ots.schemas.MIX.GPSItudeElement;
import edu.harvard.hul.ois.ots.schemas.XmlContent.Rational;
import edu.harvard.hul.ois.ots.schemas.XmlContent.XmlContentException;

/** This class represents a Mix object, with various convenient functions for use by
*  XmlContentConverter in building up the structure. It's a captive class with no
*  public interface, so data fields are directly accessible.
*/
public class MixModel {

    protected Mix mix;
    protected BasicDigitalObjectInformation bdoi;
    protected BasicImageInformation bii;
    protected BasicImageCharacteristics bic;
    protected PhotometricInterpretation phi;
    protected ImageCaptureMetadata icm;
    protected ImageAssessmentMetadata iam;
    protected SpatialMetrics sm;
    protected ImageColorEncoding ice;
    protected GeneralCaptureInformation gci;
    protected ColorProfile cp;
    protected YCbCr ycbcr;
    protected SpecialFormatCharacteristics sfc;
    protected JPEG2000 jp2000;
    protected EncodingOptions eo;
    protected Tiles tiles;
    protected WhitePoint wp;
    protected PrimaryChromaticities pc;
    protected ScannerCapture sc;
    protected ScannerModel scanm;
    protected ScanningSystemSoftware sss;
    protected DigitalCameraCapture dcc;
    protected DigitalCameraModel dcm;
    protected CameraCaptureSettings ccs;
    protected IccProfile iccp;
    protected ImageData id;
    protected SubjectDistance sd;
    protected GPSData gps;
    protected Colormap cm;
   
   
   
    protected MixModel () {
        mix = new Mix ();
        try {
             // Add the top-level elements to the mix element, to make life simpler.
            bdoi = new BasicDigitalObjectInformation();
            mix.setBasicDigitalObjectInformation(bdoi);
            bii = new BasicImageInformation ();
            mix.setBasicImageInformation (bii);
            bic = new BasicImageCharacteristics ();
            bii.setBasicImageCharacteristics (bic);
            phi = new PhotometricInterpretation ();
            bic.setPhotometricInterpetation(phi);
            icm = new ImageCaptureMetadata ();
            mix.setImageCaptureMetadata(icm);
            iam = new ImageAssessmentMetadata();
            mix.setImageAssessmentMetadata(iam);
            sm = new SpatialMetrics ();
            iam.setSpatialMetrics(sm);
            ice = new ImageColorEncoding ();
            iam.setImageColorEncoding(ice);
            gci = new GeneralCaptureInformation ();
            icm.setGeneralCaptureInformation(gci);
           
            // Here are some pieces which are constructed once, but added only if they're needed.
            cp = new ColorProfile ();           // Add this to phi if needed
            iccp = new IccProfile();            // Add this to cp if needed
            ycbcr = new YCbCr ();               // Add this to phi if needed
            sfc = new SpecialFormatCharacteristics()// Add this to bii if needed
            jp2000 = new JPEG2000 ();           // Add this to sfc if needed
            eo = new EncodingOptions ();
            tiles = new Tiles ();               // Add this to eo if needed
            wp = null;                          // We leave this null so we can tell if it's been created
            pc = null;                          // We leave this null so we can tell if it's been created
            sc = new ScannerCapture ();         // Add this to icm if needed
            scanm = new ScannerModel ();        // Add this to sc if needed
            sss = new ScanningSystemSoftware ()// add this to sc if needed
            id = new ImageData ();              // Add this to ccs if needed
            gps = new GPSData ();               // Add this to ccs if needed
            sd = new SubjectDistance ();        // Add this to id if needed
           
            // Build DigitalCameraCapture with subelements, but don't hook it to icm
            // until it's needed.
            dcc = new DigitalCameraCapture ();
            dcm = new DigitalCameraModel ();
            dcc.setDigitalCameraModel(dcm);
            ccs = new CameraCaptureSettings ();
            dcc.setCameraCaptureSettings(ccs);
           
            cm = new Colormap();
        }
        catch (XmlContentException e) {
            // Should never happen, unless the code is buggy
        }
    }
   
    /** Fill out a YCbCrSubSampling element, tokenizing the value */
    protected void populateYCbCrSS (YCbCrSubSampling ycbcrss, String data) {
        // Separation by spaces is easy material for an ordinary StringTokenizer
        StringTokenizer tok = new StringTokenizer (data);
        int hor;
        int ver;
        try {
            hor = Integer.parseInt (tok.nextToken ());
            ver = Integer.parseInt (tok.nextToken ());
        }
        catch (Exception e) {
            // Malformed data
            return;
        }
        try {
            ycbcr.setYCbCrSubSampling(ycbcrss);
            ycbcrss.setYCbCrSubsampleHoriz(hor);
            ycbcrss.setYCbCrSubsampleVert(ver);
            phi.setYCbCr(ycbcr);
        }
        catch (XmlContentException e) {
        }
    }
   
    protected void populateYCbCrCoefficients (String data) {
        StringTokenizer tok = new StringTokenizer (data);
        double red;
        double green;
        double blue;
        try {
            red = Double.parseDouble (tok.nextToken ());
            green = Double.parseDouble (tok.nextToken ());
            blue = Double.parseDouble (tok.nextToken ());
        }
        catch (Exception e) {
            // Malformed data
            return;
        }
        YCbCrCoefficients ycbcrc = new YCbCrCoefficients ();
        try {
            ycbcr.setYCbCrCoefficients(ycbcrc);
            phi.setYCbCr (ycbcr);
            ycbcrc.setLumaRed(new Rational ((int) (red * 100), 100));
            ycbcrc.setLumaGreen(new Rational ((int) (green * 100), 100));
            ycbcrc.setLumaBlue(new Rational ((int) (blue * 100), 100));
        }
        catch (XmlContentException e) {}
    }
   
   
    protected void populateJPEG2000 () {
        try {
            bii.setSpecialFormatCharacteristics(sfc);
            sfc.setJPEG2000(jp2000);
            jp2000.setEncodingOptions(eo);
            eo.setTiles(tiles);
        }
        catch (XmlContentException e) {
        }
    }
   
    protected void populateWhitePoint () {
        try {
            if (wp == null) {
                wp = new WhitePoint ();
                ice.addWhitePoint (wp);
            }
        }
        catch (XmlContentException e) {
        }
    }
   
    protected void populatePrimaryChromaticities () {
        try {
            if (pc == null) {
                pc = new PrimaryChromaticities ();
                ice.addPrimaryChromaticities(pc);
            }
        }
        catch (XmlContentException e) {
        }
    }
   
   
    protected void setBitsPerSample (int intBPS) {
        // I assume there's only a single value provided, and that it's an integer.
        // MIX allows for a different value for each component.
        try {
            BitsPerSample bps = new BitsPerSample ();
            bps.setBitsPerSampleUnit ("integer");
            bps.addBitsPerSampleValue(intBPS);
            ice.setBitsPerSample (bps);
        }
        catch (XmlContentException e) {
        }
    }
   
   

    /** Make the ColorProfile and ICCProfile part of the MIX */
    protected void attachIccp () {
        try {
            phi.setColorProfile(cp);
            cp.setIccProfile(iccp);
        }
        catch (XmlContentException e) {}
    }
   
    /** Make the ScannerCapture part of the MIX */
    protected void attachScannerCapture () {
        try {
            icm.setScannerCapture (sc);
        }
        catch (XmlContentException e) {}
    }
   
    protected void attachScanningSystemSoftware () {
        try {
            icm.setScannerCapture (sc);
            sc.setScanningSystemSoftware(sss);
        }
        catch (XmlContentException e) {}
    }
   
    protected void attachImageData () {
        try {
            ccs.setImageData (id);
            sc.setScanningSystemSoftware(sss);
            icm.setDigitalCameraCapture (dcc);
            // The links in between are already set up
        }
        catch (XmlContentException e) {}
    }
   
    protected void attachGPSData () {
        try {
            ccs.setGPSData (gps);
            sc.setScanningSystemSoftware(sss);
            icm.setDigitalCameraCapture (dcc);
            // The links in between are already set up
        }
        catch (XmlContentException e) {}
    }

    protected void populateGPSLongitude (String longitude) {
        attachGPSData ();
        GPSLongitude longit = new GPSLongitude ();
        parseItude (longit, longitude);
        try {
            gps.setGPSLongitude(longit);
        }
        catch (XmlContentException e) {}
    }

    protected void populateGPSLatitude (String latitude) {
        attachGPSData ();
        GPSLatitude latit = new GPSLatitude ();
        parseItude (latit, latitude);
        try {
            gps.setGPSLatitude(latit);
        }
        catch (XmlContentException e) {}
    }

    protected void populateGPSDestLongitude (String longitude) {
        attachGPSData ();
        GPSDestLongitude longit = new GPSDestLongitude ();
        parseItude (longit, longitude);
        try {
            gps.setGPSDestLongitude(longit);
        }
        catch (XmlContentException e) {}
    }

    protected void populateGPSDestLatitude (String latitude)  {
        attachGPSData ();
        GPSDestLatitude latit = new GPSDestLatitude ();
        parseItude (latit, latitude);
        try {
            gps.setGPSDestLatitude(latit);
        }
        catch (XmlContentException e) {}
    }
   
    protected void populateReferenceBlackWhite (String data, String colorspace) {
        /* This consists of a series of six numbers, separated by spaces, each of which
         * is a headroom-footroom pair. The second argument tells us whether
         * the components are yCbCr or RGB. For the current cut, assume YCbCr.
         */
        StringTokenizer tok = new StringTokenizer (data);
        boolean rgb = ("RGB".equals (colorspace));
        double rbwVal[] = new double[6];
        try {
            for (int i = 0; i < 6; i++) {
                rbwVal[i] = Double.parseDouble(tok.nextToken());
            }
        }
        catch (Exception e) {
            return;
        }
        try {
            ReferenceBlackWhite rbw = new ReferenceBlackWhite ();
            phi.addReferenceBlackWhite(rbw);
            for (int i = 0; i < 6; i += 2) {
                Component comp = new Component ();
                rbw.addComponent(comp);
                String interp;
                switch (i) {
                case 0:
                    if (rgb)
                        interp = "R";
                    else
                        interp = "Y";
                    break;
                case 2:
                    if (rgb)
                        interp = "G";
                    else
                        interp = "Cb";
                    break;
                default:
                    if (rgb)
                        interp = "B";
                    else
                        interp = "Cr";
                    break;
                }
                comp.setComponentPhotometricInterpretation(interp);
                comp.setHeadroom (new Rational ((int) (rbwVal[i] * 100), 100));
                comp.setFootroom (new Rational ((int) (rbwVal[i+1] * 100), 100));
            }
        }
        catch (XmlContentException e) {}
    }

    /** Make the ScannerModel part of the MIX */
    protected void attachScannerModel () {
        try {
            icm.setScannerCapture (sc);
            sc.setScannerModel (scanm);
        }
        catch (XmlContentException e) {}
    }
   
    /** Make the Colormap part of the MIX */
    protected void attachColorMap () {
        try {
            ice.setColormap (cm);
        }
        catch (XmlContentException e) {}
    }
   
    protected void attachSubjectDistance () {
        try {
            id.setSubjectDistance (sd);
            ccs.setImageData (id);
            icm.setDigitalCameraCapture (dcc);
            // The links in between are already set up
        }
        catch (XmlContentException e) {}
    }

    /** Parse the longitude or latitude string from ExifTool. This is in
     *  a rather ugly format, like this:
     *  33 deg 24' 51.80" N
     */
    private void parseItude (GPSItudeElement elem, String itude) {
        StringBuffer itudeBuf = new StringBuffer (itude);
        // Get rid of the non-number portions
        try {
            int pos = itudeBuf.indexOf ("deg ");
            if (pos > 0)
                itudeBuf.delete (pos, pos + 4);
            pos = itudeBuf.indexOf ("\"");
            if (pos > 0)
                itudeBuf.deleteCharAt(pos);
            pos = itudeBuf.indexOf ("'");
            if (pos > 0)
                itudeBuf.deleteCharAt(pos);

            // Now we should just have three numbers separated by spaces.
            // Fractional degrees or minutes don't make much sense given that
            // seconds exist, so treat only seconds as a double.
            StringTokenizer tok = new StringTokenizer (itudeBuf.toString());
            int deg = 0;
            int min = 0;
            double sec = 0;
           
            deg = Integer.parseInt (tok.nextToken ());
            if (tok.hasMoreElements())
                min = Integer.parseInt (tok.nextToken ());
            if (tok.hasMoreElements())
                sec = Double.parseDouble (tok.nextToken ());
           
            elem.setDegrees (new Rational (deg, 1));
            elem.setMinutes (new Rational (min, 1));
            elem.setSeconds (new Rational ((int) (sec * 100), 100));
        }
        catch (Exception e) {
        }
    }
}
TOP

Related Classes of edu.harvard.hul.ois.fits.MixModel

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.