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

com.nmote.iim4j.stream.JPEGIIMInputStream Maven / Gradle / Ivy

Go to download

IIM4J allows Java programmers to read, write and process IPTC IIM version 4 files.

The newest version!
/*
 * Copyright (c) Nmote Ltd. 2004-2015. All rights reserved.
 * See LICENSE doc in a root of project folder for additional information.
 */

package com.nmote.iim4j.stream;

import java.io.EOFException;
import java.io.IOException;

/**
 * This is an IIMInputStream implementation that parses IPTC data embedded into
 * JFIF (JPEG) files.
 */
public class JPEGIIMInputStream extends SubIIMInputStream {

	public JPEGIIMInputStream(IIMInputStream input) throws IOException {
		super(input);

		// Check JPEG header magic number
		if (JPEGUtil.readInt8(input) != JPEGUtil.START || JPEGUtil.readInt8(input) != 0xD8) {
			throw new IOException("not a JPEG file (invalid magic number)");
		}

		for (;;) {
			// SegmentStart - 0xFF
			if (JPEGUtil.readInt8(input) != JPEGUtil.START) {
				throw new IOException("expected JPEG segment start identifier");
			}

			// SegmentMarker
			int segmentMarker = JPEGUtil.readInt8(input);

			// This is last segment and no IIM data was found
			if (segmentMarker == JPEGUtil.SOS) {
				throw new IIMNotFoundException();
			}

			// SegmentSize: High-byte Low-byte
			int segmentSize = JPEGUtil.readInt16(input);

			// Segment size includes size bytes, so subtract two bytes from size
			segmentSize -= 2;

			if (segmentMarker == JPEGUtil.APPD) {
				if (input.isCached()) {
					// Substract skipped 8BIM headers from segment size
					segmentSize -= findStartTag(input);
				}
				setOffsetAndLength(input.position(), segmentSize);
				break;
			} else {
				// Skip this segment
				input.seek(input.position() + segmentSize);
			}
		}
	}

	private static int findStartTag(IIMInputStream input) throws IOException {
		long start = input.position();
		int tag = input.read();
		while (tag != 28) {
			if (tag == -1) {
				// We've reached EOF, no more datasets to return
				throw new EOFException("Can't find 0x1C marker in APPD segment");
			}
			tag = input.read();
		}
		long pos = input.position() - 1;
		input.seek(pos);
		return (int) (pos - start);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy