private void Initialize(RandomAccessFileOrArray stream) {
long nextTagOffset = 0L;
long maxOffset = (long) stream.Length;
int i, j;
IFDOffset = stream.FilePointer;
numEntries = ReadUnsignedShort(stream);
fields = new TIFFField[numEntries];
for (i = 0; (i < numEntries) && (nextTagOffset < maxOffset); i++) {
int tag = ReadUnsignedShort(stream);
int type = ReadUnsignedShort(stream);
int count = (int)(ReadUnsignedInt(stream));
bool processTag = true;
// The place to return to to read the next tag
nextTagOffset = stream.FilePointer + 4;
try {
// If the tag data can't fit in 4 bytes, the next 4 bytes
// contain the starting offset of the data
if (count*sizeOfType[type] > 4) {
long valueOffset = ReadUnsignedInt(stream);
// bounds check offset for EOF
if (valueOffset < maxOffset) {
stream.Seek(valueOffset);
}
else {
// bad offset pointer .. skip tag
processTag = false;
}
}
} catch (ArgumentOutOfRangeException) {
// if the data type is unknown we should skip this TIFF Field
processTag = false;
}
if (processTag) {
fieldIndex[tag] = i;
Object obj = null;
switch (type) {
case TIFFField.TIFF_BYTE:
case TIFFField.TIFF_SBYTE:
case TIFFField.TIFF_UNDEFINED:
case TIFFField.TIFF_ASCII:
byte[] bvalues = new byte[count];
stream.ReadFully(bvalues, 0, count);
if (type == TIFFField.TIFF_ASCII) {
// Can be multiple strings
int index = 0, prevIndex = 0;
ArrayList v = new ArrayList();
while (index < count) {
while ((index < count) && (bvalues[index++] != 0));
// When we encountered zero, means one string has ended
char[] cht = new char[index - prevIndex];
Array.Copy(bvalues, prevIndex, cht, 0, index - prevIndex);
v.Add(new String(cht));
prevIndex = index;
}
count = v.Count;
String[] strings = new String[count];
for (int c = 0 ; c < count; c++) {
strings[c] = (String)v[c];
}
obj = strings;
} else {
obj = bvalues;
}
break;
case TIFFField.TIFF_SHORT:
char[] cvalues = new char[count];
for (j = 0; j < count; j++) {
cvalues[j] = (char)(ReadUnsignedShort(stream));
}
obj = cvalues;
break;
case TIFFField.TIFF_LONG:
long[] lvalues = new long[count];
for (j = 0; j < count; j++) {
lvalues[j] = ReadUnsignedInt(stream);
}
obj = lvalues;
break;
case TIFFField.TIFF_RATIONAL:
long[][] llvalues = new long[count][];
for (j = 0; j < count; j++) {
long v0 = ReadUnsignedInt(stream);
long v1 = ReadUnsignedInt(stream);
llvalues[j] = new long[]{v0, v1};
}
obj = llvalues;
break;
case TIFFField.TIFF_SSHORT:
short[] svalues = new short[count];
for (j = 0; j < count; j++) {
svalues[j] = ReadShort(stream);
}
obj = svalues;
break;
case TIFFField.TIFF_SLONG:
int[] ivalues = new int[count];
for (j = 0; j < count; j++) {
ivalues[j] = ReadInt(stream);
}
obj = ivalues;
break;
case TIFFField.TIFF_SRATIONAL:
int[,] iivalues = new int[count,2];
for (j = 0; j < count; j++) {
iivalues[j,0] = ReadInt(stream);
iivalues[j,1] = ReadInt(stream);
}
obj = iivalues;
break;
case TIFFField.TIFF_FLOAT:
float[] fvalues = new float[count];
for (j = 0; j < count; j++) {
fvalues[j] = ReadFloat(stream);
}
obj = fvalues;
break;
case TIFFField.TIFF_DOUBLE:
double[] dvalues = new double[count];
for (j = 0; j < count; j++) {
dvalues[j] = ReadDouble(stream);
}
obj = dvalues;
break;
default:
break;
}
fields[i] = new TIFFField(tag, type, count, obj);
}
stream.Seek(nextTagOffset);
}
// Read the offset of the next IFD.
try {
nextIFDOffset = ReadUnsignedInt(stream);
}
catch {
// broken tiffs may not have this pointer
nextIFDOffset = 0;
}
}