package com.almalence.plugins.export.ExifDriver.Values; import com.almalence.plugins.export.ExifDriver.ExifDriver; /** * Parent class of all EXIF datatypes. */ public abstract class ExifValue { protected int dataType; public ExifValue(int _dataType) { dataType = _dataType; } /** * Read it's value from a given source * * @param _data * Source array to read from * @param _offset * Offset where to start reading * @param _count * Amount of bytes to read * @param _align * Endian - is ignored by ASCII and UNDEFINED */ public abstract void readValueFromData(byte[] _data, int _offset, int _count, int _align); /** * Returns byte array of components * * @return Array of components * @throws UndefinedValueAccessException */ public byte[] getBytes() throws UndefinedValueAccessException { throw new UndefinedValueAccessException("Function is undefined in " + getClass().getSimpleName()); } /** * Returns int [] of components * * @return Array of components * @throws UndefinedValueAccessException */ public int[] getIntegers() throws UndefinedValueAccessException { throw new UndefinedValueAccessException("Function is undefined in " + getClass().getSimpleName()); } /** * Returns int [][2] of components * * @return Array of components * @throws UndefinedValueAccessException */ public int[][] getRationals() throws UndefinedValueAccessException { throw new UndefinedValueAccessException("Function is undefined in " + getClass().getSimpleName()); } /** * Set byte array of values * * @param _values * @throws UndefinedValueAccessException */ public void setBytes(byte[] _bytes) throws UndefinedValueAccessException { throw new UndefinedValueAccessException("Function is undefined in " + getClass().getSimpleName()); } /** * Set int[] of values * * @param _values * @throws UndefinedValueAccessException */ public void setIntegers(int[] _values) throws UndefinedValueAccessException { throw new UndefinedValueAccessException("Function is undefined in " + getClass().getSimpleName()); } /** * Set int[][] array of values * * @param _values * @throws UndefinedValueAccessException */ public void setRationals(int[][] _values) throws UndefinedValueAccessException { throw new UndefinedValueAccessException("Function is undefined in " + getClass().getSimpleName()); } /** * Returns size of one single component. For example if Value holds components * of type UNSIGNED_BYTE, it returns 1. * * @return Size of one single component * @throws UndefinedValueAccessException */ public final int getComponentSize() { return ExifDriver.COMP_WIDTHS[dataType]; } /** * Total size of components. In case that value holds 4 components of type * UNSIGNED_SHORT, it returns 8; * * @return Total size of components * @throws UndefinedValueAccessException */ public final int getTotalSize() { return getNbfComponents() * getComponentSize(); } /** * Returns of extra space that this value needs. All values store their * components right into directory if their total amount is less then 4B. In * opposite case they stores to directory only offset, where the data are * stored. Extra space is therefore 0 or totalLength of data. * * @return Extra space that this value uses */ public final int getExtraSize() { if (getTotalSize() > 4) { return getTotalSize(); } else { return 0; } } /** * Returns number of value's components * * @return Extra space that this value uses * @throws UndefinedValueAccessException */ public abstract int getNbfComponents(); /** * This method implements the special way, in which the value saves it's * components. * * @param _data * - output array * @param _offset * - offset where to save the components */ protected abstract void writeValues(byte[] _data, int _offset); /** * Write this component to specified place in output data. * * @param _data * Output data array * @param _itemOffset * Offset of IFD directory record * @param _valuesOffset * Offset of the first free byte in IFD's data * @return Offset of the first free byte in IFD's data. In case, that the * value does not use any extra space, return value will equal to * _valuesOffset. * @throws UndefinedValueAccessException */ public final int writeToData(byte[] _data, int _itemOffset, int _valuesOffset) { ExifDriver.writeNumber(_data, _itemOffset + 2, dataType, 2); ExifDriver.writeNumber(_data, _itemOffset + 4, getNbfComponents(), 4); int valueOffset = _itemOffset + 8; int extraSpace = getExtraSize(); if (extraSpace > 0) { ExifDriver.writeNumber(_data, valueOffset, _valuesOffset, 4); writeValues(_data, _valuesOffset); return _valuesOffset + extraSpace; } else { writeValues(_data, valueOffset); return _valuesOffset; } } /** * Returns the datatype of this value * * @return Datatype */ public final int getDataType() { return dataType; } }