view dwt/internal/image/JPEGFrameHeader.d @ 13:3d9bbe0a83a0

FileFormats
author Frank Benoit <benoit@tionex.de>
date Sun, 06 Jan 2008 22:54:14 +0100
parents
children fc2b263b8a3f
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
module dwt.internal.image.JPEGFrameHeader;


import dwt.SWT;
import dwt.internal.image.JPEGVariableSizeSegment;
import dwt.internal.image.JPEGFileFormat;
import dwt.internal.image.LEDataInputStream;

final class JPEGFrameHeader : JPEGVariableSizeSegment {
	int maxVFactor;
	int maxHFactor;
	public int[] componentIdentifiers;
	public int[][] componentParameters;

	public this(byte[] reference) {
		super(reference);
	}

	public this(LEDataInputStream byteStream) {
		super(byteStream);
		initializeComponentParameters();
	}

	public int getSamplePrecision() {
		return reference[4] & 0xFF;
	}

	public int getNumberOfLines() {
		return (reference[5] & 0xFF) << 8 | (reference[6] & 0xFF);
	}

	public int getSamplesPerLine() {
		return (reference[7] & 0xFF) << 8 | (reference[8] & 0xFF);
	}

	public int getNumberOfImageComponents() {
		return reference[9] & 0xFF;
	}

	public void setSamplePrecision(int precision) {
		reference[4] = cast(byte)(precision & 0xFF);
	}

	public void setNumberOfLines(int anInteger) {
		reference[5] = cast(byte)((anInteger & 0xFF00) >> 8);
		reference[6] = cast(byte)(anInteger & 0xFF);
	}

	public void setSamplesPerLine(int samples) {
		reference[7] = cast(byte)((samples & 0xFF00) >> 8);
		reference[8] = cast(byte)(samples & 0xFF);
	}

	public void setNumberOfImageComponents(int anInteger) {
		reference[9] = cast(byte)(anInteger & 0xFF);
	}

	public int getMaxHFactor() {
		return maxHFactor;
	}

	public int getMaxVFactor() {
		return maxVFactor;
	}

	public void setMaxHFactor(int anInteger) {
		maxHFactor = anInteger;
	}

	public void setMaxVFactor(int anInteger) {
		maxVFactor = anInteger;
	}

	/* Used when decoding. */
	void initializeComponentParameters() {
		int nf = getNumberOfImageComponents();
		componentIdentifiers = new int[nf];
		int[][] compSpecParams;
		int hmax = 1;
		int vmax = 1;
		for (int i = 0; i < nf; i++) {
			int ofs = i * 3 + 10;
			int ci = reference[ofs] & 0xFF;
			componentIdentifiers[i] = ci;
			int hi = (reference[ofs + 1] & 0xFF) >> 4;
			int vi = reference[ofs + 1] & 0xF;
			int tqi = reference[ofs + 2] & 0xFF;
			if (hi > hmax) {
				hmax = hi;
			}
			if (vi > vmax) {
				vmax = vi;
			}
			int[] compParam = new int[5];
			compParam[0] = tqi;
			compParam[1] = hi;
			compParam[2] = vi;
			if (compSpecParams.length <= ci) {
				compSpecParams.length = ci + 1;
			}
			compSpecParams[ci] = compParam;
		}
		int x = getSamplesPerLine();
		int y = getNumberOfLines();
		int[] multiples = [ 8, 16, 24, 32 ];
		for (int i = 0; i < nf; i++) {
			int[] compParam = compSpecParams[componentIdentifiers[i]];
			int hi = compParam[1];
			int vi = compParam[2];
			int compWidth = (x * hi + hmax - 1) / hmax;
			int compHeight = (y * vi + vmax - 1) / vmax;
			int dsWidth = roundUpToMultiple(compWidth, multiples[hi - 1]);
			int dsHeight = roundUpToMultiple(compHeight, multiples[vi - 1]);
			compParam[3] = dsWidth;
			compParam[4] = dsHeight;
		}
		setMaxHFactor(hmax);
		setMaxVFactor(vmax);
		componentParameters = compSpecParams;
	}

	/* Used when encoding. */
	public void initializeContents() {
		int nf = getNumberOfImageComponents();
		if (nf == 0 || nf != componentParameters.length) {
			SWT.error(SWT.ERROR_INVALID_IMAGE);
		}
		int hmax = 0;
		int vmax = 0;
		int[][] compSpecParams = componentParameters;
		for (int i = 0; i < nf; i++) {
			int ofs = i * 3 + 10;
			int[] compParam = compSpecParams[componentIdentifiers[i]];
			int hi = compParam[1];
			int vi = compParam[2];
			if (hi * vi > 4) {
				SWT.error(SWT.ERROR_INVALID_IMAGE);
			}
			reference[ofs] = cast(byte)(i + 1);
			reference[ofs + 1] = cast(byte)(hi * 16 + vi);
			reference[ofs + 2] = cast(byte)(compParam[0]);
			if (hi > hmax) hmax = hi;
			if (vi > vmax) vmax = vi;
		}
		int x = getSamplesPerLine();
		int y = getNumberOfLines();
		int[] multiples = [8, 16, 24, 32];
		for (int i = 0; i < nf; i++) {
			int[] compParam = compSpecParams[componentIdentifiers[i]];
			int hi = compParam[1];
			int vi = compParam[2];
			int compWidth = (x * hi + hmax - 1) / hmax;
			int compHeight = (y * vi + vmax - 1) / vmax;
			int dsWidth = roundUpToMultiple(compWidth, multiples[hi - 1]);
			int dsHeight = roundUpToMultiple(compHeight, multiples[vi - 1]);
			compParam[3] = dsWidth;
			compParam[4] = dsHeight;
		}
		setMaxHFactor(hmax);
		setMaxVFactor(vmax);
	}

	int roundUpToMultiple(int anInteger, int mInteger) {
		int a = anInteger + mInteger - 1;
		return a - (a % mInteger);
	}

	/*
	 * Verify the information contained in the receiver is correct.
	 * Answer true if the header contains a valid marker. Otherwise,
	 * answer false. Valid Start Of Frame markers are:
	 *	SOF_0  - Baseline DCT, Huffman coding
	 *	SOF_1  - Extended sequential DCT, Huffman coding
	 *	SOF_2  - Progressive DCT, Huffman coding
	 *	SOF_3  - Lossless (sequential), Huffman coding
	 *	SOF_5  - Differential sequential, Huffman coding
	 *	SOF_6  - Differential progressive, Huffman coding
	 *	SOF_7  - Differential lossless, Huffman coding
	 *	SOF_9  - Extended sequential DCT, arithmetic coding
	 *	SOF_10 - Progressive DCT, arithmetic coding
	 *	SOF_11 - Lossless (sequential), arithmetic coding
	 *	SOF_13 - Differential sequential, arithmetic coding
	 *	SOF_14 - Differential progressive, arithmetic coding
	 *	SOF_15 - Differential lossless, arithmetic coding
	 */
	public bool verify() {
		int marker = getSegmentMarker();
		return (marker >= JPEGFileFormat.SOF0 && marker <= JPEGFileFormat.SOF3) ||
			(marker >= JPEGFileFormat.SOF5 && marker <= JPEGFileFormat.SOF7) ||
			(marker >= JPEGFileFormat.SOF9 && marker <= JPEGFileFormat.SOF11) ||
			(marker >= JPEGFileFormat.SOF13 && marker <= JPEGFileFormat.SOF15);
	}

	public bool isProgressive() {
		int marker = getSegmentMarker();
		return marker == JPEGFileFormat.SOF2
			|| marker == JPEGFileFormat.SOF6
			|| marker == JPEGFileFormat.SOF10
			|| marker == JPEGFileFormat.SOF14;
	}

	public bool isArithmeticCoding() {
		return getSegmentMarker() >= JPEGFileFormat.SOF9;
	}
}