All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.monte.media.mpo.MPOImageReader Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
/*
 * @(#)MPOImageReader.java  1.1  2011-02-01
 * 
 * Copyright (c) 2009-2011 Werner Randelshofer, Goldau, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package org.monte.media.mpo;

import org.monte.media.io.SubImageInputStream;
import org.monte.media.exif.DefaultIIOMetadata;
import org.monte.media.exif.EXIFReader;
import org.monte.media.exif.EXIFTagSet;
import org.monte.media.exif.MPEntryTagSet;
import org.monte.media.exif.MPFTagSet;
import org.monte.media.tiff.TIFFDirectory;
import org.monte.media.tiff.TIFFField;
import org.monte.media.tiff.TIFFNode;
import org.monte.media.tiff.TIFFTag;
import com.sun.imageio.plugins.jpeg.JPEGImageReader;
import java.awt.image.BufferedImage;
import java.awt.image.DirectColorModel;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import org.monte.media.jpeg.CMYKJPEGImageReader;

/**
 * Reads an image in the MultiPicture Object format (MPO).
 * 

* See: MPO Format Specification. * * @author Werner Randelshofer * @version 1.1 2011-02-01 Improves performance of method getImageMetadata. *
1.0 2009-12-14 Created. */ public class MPOImageReader extends ImageReader { private static DirectColorModel RGB = new DirectColorModel(24, 0xff0000, 0xff00, 0xff, 0x0); /** Number of images. -1 if not known. */ private int numImages = -1; /** Image offsets. null if not known. */ private long[] imageOffsets; /** Image lengths. null if not known. */ private long[] imageLengths; /** Thumbnail offsets. null if not known. */ private long[] thumbOffsets; /** Thumbnail lengths. null if not known. */ private long[] thumbLengths; /** Width of the images. */ private int width = -1; /** Height of the images. */ private int height = -1; /** Metadata of all images. */ private IIOMetadata[] imageMetadata; private EXIFReader er; public MPOImageReader(MPOImageReaderSpi originatingProvider) { super(originatingProvider); } @Override public int getNumImages(boolean allowSearch) throws IOException { if (allowSearch && numImages == -1) { readHeader(); } return numImages; } @Override public int getWidth(int imageIndex) throws IOException { readHeader(); return width; } @Override public int getHeight(int imageIndex) throws IOException { readHeader(); return height; } @Override public Iterator getImageTypes(int imageIndex) throws IOException { readHeader(); LinkedList l = new LinkedList(); l.add(new ImageTypeSpecifier(RGB, RGB.createCompatibleSampleModel(width, height))); return l.iterator(); } @Override public IIOMetadata getStreamMetadata() throws IOException { return null; } @Override public IIOMetadata getImageMetadata(int imageIndex) throws IOException { readHeader(); return imageMetadata[imageIndex]; } @Override public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { readHeader(); ImageInputStream in = (ImageInputStream) getInput(); SubImageInputStream sin = new SubImageInputStream(in, imageOffsets[imageIndex], imageLengths[imageIndex]); sin.seek(0); ImageReader ir = new CMYKJPEGImageReader(getOriginatingProvider()); ir.setInput(sin); BufferedImage img = ir.read(0); ir.dispose(); return img; } @Override public int getNumThumbnails(int imageIndex) throws IOException { readHeader(); return super.getNumThumbnails(imageIndex); } /** Reads the header. * Does nothing if the header has already been loaded. */ private void readHeader() throws IOException { if (numImages == -1) { ImageInputStream in = (ImageInputStream) getInput(); in.seek(0); er = new EXIFReader(in); er.setFirstImageOnly(false); er.read(); // Get some information that is easy to obtain through a map { HashMap m = er.getMetaDataMap(); TIFFField mde; if ((mde = m.get(MPFTagSet.get(MPFTagSet.TAG_NumberOfImages))) != null) { numImages = ((Number) mde.getData()).intValue(); } else { numImages = 1; } if ((mde = m.get(EXIFTagSet.PixelXDimension)) != null) { width = ((Number) mde.getData()).intValue(); } if ((mde = m.get(EXIFTagSet.PixelYDimension)) != null) { height = ((Number) mde.getData()).intValue(); } } imageOffsets = new long[numImages]; imageLengths = new long[numImages]; if (numImages == 1) { imageOffsets[0] = 0; imageLengths[0] = in.length(); } // Get now at the tough part int index = 0; for (Iterator e = er.getMetaDataTree().preorderIterator(); e.hasNext();) { TIFFNode n = e.next(); if (n instanceof TIFFDirectory) { TIFFDirectory dir = (TIFFDirectory) n; //System.out.println("dir:" + dir.getName()); if (dir.getName() != null && dir.getName().equals("MPEntry")) { long dirOffset = dir.getFileSegments().get(0).getOffset(); TIFFField offsetField = dir.getField(MPEntryTagSet.IndividualImageDataOffset); TIFFField lengthField = dir.getField(MPEntryTagSet.IndividualImageSize); if (offsetField != null && lengthField != null) { long dataOffset = (Long) offsetField.getData(); imageOffsets[index] = dataOffset == 0 ? 0 : dirOffset + dataOffset; imageLengths[index] = (Long) lengthField.getData(); index++; } } } } // Store metadata for later access String formatName = "com_sun_media_imageio_plugins_tiff_image_1.0"; imageMetadata = new IIOMetadata[numImages]; for (int i = 0; i < numImages; i++) { imageMetadata[i] = new DefaultIIOMetadata(formatName, er.getIIOMetadataTree(formatName, i)); } in.seek(0); } } public TIFFNode getExifMetadata() throws IOException { readHeader(); return er.getMetaDataTree(); } public EXIFReader getExifReader() throws IOException { readHeader(); return er; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy