/// <summary>Processes a TIFF data sequence.</summary>
        /// <param name="reader">
        /// the
        /// <see cref="Com.Drew.Lang.RandomAccessReader"/>
        /// from which the data should be read
        /// </param>
        /// <param name="handler">
        /// the
        /// <see cref="TiffHandler"/>
        /// that will coordinate processing and accept read values
        /// </param>
        /// <param name="tiffHeaderOffset">the offset within <code>reader</code> at which the TIFF header starts</param>
        /// <exception cref="TiffProcessingException">
        /// if an error occurred during the processing of TIFF data that could not be
        /// ignored or recovered from
        /// </exception>
        /// <exception cref="System.IO.IOException">an error occurred while accessing the required data</exception>
        /// <exception cref="Com.Drew.Imaging.Tiff.TiffProcessingException"/>
        public virtual void ProcessTiff(RandomAccessReader reader, TiffHandler handler, int tiffHeaderOffset)
        {
            // This must be either "MM" or "II".
            short byteOrderIdentifier = reader.GetInt16(tiffHeaderOffset);

            if (byteOrderIdentifier == unchecked ((int)(0x4d4d)))
            {
                // "MM"
                reader.SetMotorolaByteOrder(true);
            }
            else
            {
                if (byteOrderIdentifier == unchecked ((int)(0x4949)))
                {
                    // "II"
                    reader.SetMotorolaByteOrder(false);
                }
                else
                {
                    throw new TiffProcessingException("Unclear distinction between Motorola/Intel byte ordering: " + byteOrderIdentifier);
                }
            }
            // Check the next two values for correctness.
            int tiffMarker = reader.GetUInt16(2 + tiffHeaderOffset);

            handler.SetTiffMarker(tiffMarker);
            int firstIfdOffset = reader.GetInt32(4 + tiffHeaderOffset) + tiffHeaderOffset;

            // David Ekholm sent a digital camera image that has this problem
            // TODO getLength should be avoided as it causes RandomAccessStreamReader to read to the end of the stream
            if (firstIfdOffset >= reader.GetLength() - 1)
            {
                handler.Warn("First IFD offset is beyond the end of the TIFF data segment -- trying default offset");
                // First directory normally starts immediately after the offset bytes, so try that
                firstIfdOffset = tiffHeaderOffset + 2 + 2 + 4;
            }
            ICollection <int> processedIfdOffsets = new HashSet <int>();

            ProcessIfd(handler, reader, processedIfdOffsets, firstIfdOffset, tiffHeaderOffset);
            handler.Completed(reader, tiffHeaderOffset);
        }
Esempio n. 2
0
        private static void ProcessKodakMakernote(KodakMakernoteDirectory directory, int tagValueOffset, RandomAccessReader reader)
        {
            // Kodak's makernote is not in IFD format. It has values at fixed offsets.
            int dataOffset = tagValueOffset + 8;

            try
            {
                directory.SetString(KodakMakernoteDirectory.TagKodakModel, reader.GetString(dataOffset, 8));
                directory.SetInt(KodakMakernoteDirectory.TagQuality, reader.GetUInt8(dataOffset + 9));
                directory.SetInt(KodakMakernoteDirectory.TagBurstMode, reader.GetUInt8(dataOffset + 10));
                directory.SetInt(KodakMakernoteDirectory.TagImageWidth, reader.GetUInt16(dataOffset + 12));
                directory.SetInt(KodakMakernoteDirectory.TagImageHeight, reader.GetUInt16(dataOffset + 14));
                directory.SetInt(KodakMakernoteDirectory.TagYearCreated, reader.GetUInt16(dataOffset + 16));
                directory.SetByteArray(KodakMakernoteDirectory.TagMonthDayCreated, reader.GetBytes(dataOffset + 18, 2));
                directory.SetByteArray(KodakMakernoteDirectory.TagTimeCreated, reader.GetBytes(dataOffset + 20, 4));
                directory.SetInt(KodakMakernoteDirectory.TagBurstMode2, reader.GetUInt16(dataOffset + 24));
                directory.SetInt(KodakMakernoteDirectory.TagShutterMode, reader.GetUInt8(dataOffset + 27));
                directory.SetInt(KodakMakernoteDirectory.TagMeteringMode, reader.GetUInt8(dataOffset + 28));
                directory.SetInt(KodakMakernoteDirectory.TagSequenceNumber, reader.GetUInt8(dataOffset + 29));
                directory.SetInt(KodakMakernoteDirectory.TagFNumber, reader.GetUInt16(dataOffset + 30));
                directory.SetLong(KodakMakernoteDirectory.TagExposureTime, reader.GetUInt32(dataOffset + 32));
                directory.SetInt(KodakMakernoteDirectory.TagExposureCompensation, reader.GetInt16(dataOffset + 36));
                directory.SetInt(KodakMakernoteDirectory.TagFocusMode, reader.GetUInt8(dataOffset + 56));
                directory.SetInt(KodakMakernoteDirectory.TagWhiteBalance, reader.GetUInt8(dataOffset + 64));
                directory.SetInt(KodakMakernoteDirectory.TagFlashMode, reader.GetUInt8(dataOffset + 92));
                directory.SetInt(KodakMakernoteDirectory.TagFlashFired, reader.GetUInt8(dataOffset + 93));
                directory.SetInt(KodakMakernoteDirectory.TagIsoSetting, reader.GetUInt16(dataOffset + 94));
                directory.SetInt(KodakMakernoteDirectory.TagIso, reader.GetUInt16(dataOffset + 96));
                directory.SetInt(KodakMakernoteDirectory.TagTotalZoom, reader.GetUInt16(dataOffset + 98));
                directory.SetInt(KodakMakernoteDirectory.TagDateTimeStamp, reader.GetUInt16(dataOffset + 100));
                directory.SetInt(KodakMakernoteDirectory.TagColorMode, reader.GetUInt16(dataOffset + 102));
                directory.SetInt(KodakMakernoteDirectory.TagDigitalZoom, reader.GetUInt16(dataOffset + 104));
                directory.SetInt(KodakMakernoteDirectory.TagSharpness, reader.GetInt8(dataOffset + 107));
            }
            catch (IOException ex)
            {
                directory.AddError("Error processing Kodak makernote data: " + ex.Message);
            }
        }
        /// <exception cref="System.IO.IOException"/>
        private static void ProcessTag(TiffHandler handler, int tagId, int tagValueOffset, int componentCount, int formatCode, RandomAccessReader reader)
        {
            switch (formatCode)
            {
            case TiffDataFormat.CodeUndefined:
            {
                // this includes exif user comments
                handler.SetByteArray(tagId, reader.GetBytes(tagValueOffset, componentCount));
                break;
            }

            case TiffDataFormat.CodeString:
            {
                handler.SetString(tagId, reader.GetNullTerminatedString(tagValueOffset, componentCount));
                break;
            }

            case TiffDataFormat.CodeRationalS:
            {
                if (componentCount == 1)
                {
                    handler.SetRational(tagId, new Rational(reader.GetInt32(tagValueOffset), reader.GetInt32(tagValueOffset + 4)));
                }
                else
                {
                    if (componentCount > 1)
                    {
                        Rational[] array = new Rational[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            array[i] = new Rational(reader.GetInt32(tagValueOffset + (8 * i)), reader.GetInt32(tagValueOffset + 4 + (8 * i)));
                        }
                        handler.SetRationalArray(tagId, array);
                    }
                }
                break;
            }

            case TiffDataFormat.CodeRationalU:
            {
                if (componentCount == 1)
                {
                    handler.SetRational(tagId, new Rational(reader.GetUInt32(tagValueOffset), reader.GetUInt32(tagValueOffset + 4)));
                }
                else
                {
                    if (componentCount > 1)
                    {
                        Rational[] array = new Rational[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            array[i] = new Rational(reader.GetUInt32(tagValueOffset + (8 * i)), reader.GetUInt32(tagValueOffset + 4 + (8 * i)));
                        }
                        handler.SetRationalArray(tagId, array);
                    }
                }
                break;
            }

            case TiffDataFormat.CodeSingle:
            {
                if (componentCount == 1)
                {
                    handler.SetFloat(tagId, reader.GetFloat32(tagValueOffset));
                }
                else
                {
                    float[] array = new float[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetFloat32(tagValueOffset + (i * 4));
                    }
                    handler.SetFloatArray(tagId, array);
                }
                break;
            }

            case TiffDataFormat.CodeDouble:
            {
                if (componentCount == 1)
                {
                    handler.SetDouble(tagId, reader.GetDouble64(tagValueOffset));
                }
                else
                {
                    double[] array = new double[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetDouble64(tagValueOffset + (i * 4));
                    }
                    handler.SetDoubleArray(tagId, array);
                }
                break;
            }

            case TiffDataFormat.CodeInt8S:
            {
                if (componentCount == 1)
                {
                    handler.SetInt8s(tagId, reader.GetInt8(tagValueOffset));
                }
                else
                {
                    sbyte[] array = new sbyte[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetInt8(tagValueOffset + i);
                    }
                    handler.SetInt8sArray(tagId, array);
                }
                break;
            }

            case TiffDataFormat.CodeInt8U:
            {
                if (componentCount == 1)
                {
                    handler.SetInt8u(tagId, reader.GetUInt8(tagValueOffset));
                }
                else
                {
                    short[] array = new short[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetUInt8(tagValueOffset + i);
                    }
                    handler.SetInt8uArray(tagId, array);
                }
                break;
            }

            case TiffDataFormat.CodeInt16S:
            {
                if (componentCount == 1)
                {
                    handler.SetInt16s(tagId, (int)reader.GetInt16(tagValueOffset));
                }
                else
                {
                    short[] array = new short[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetInt16(tagValueOffset + (i * 2));
                    }
                    handler.SetInt16sArray(tagId, array);
                }
                break;
            }

            case TiffDataFormat.CodeInt16U:
            {
                if (componentCount == 1)
                {
                    handler.SetInt16u(tagId, reader.GetUInt16(tagValueOffset));
                }
                else
                {
                    int[] array = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetUInt16(tagValueOffset + (i * 2));
                    }
                    handler.SetInt16uArray(tagId, array);
                }
                break;
            }

            case TiffDataFormat.CodeInt32S:
            {
                // NOTE 'long' in this case means 32 bit, not 64
                if (componentCount == 1)
                {
                    handler.SetInt32s(tagId, reader.GetInt32(tagValueOffset));
                }
                else
                {
                    int[] array = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetInt32(tagValueOffset + (i * 4));
                    }
                    handler.SetInt32sArray(tagId, array);
                }
                break;
            }

            case TiffDataFormat.CodeInt32U:
            {
                // NOTE 'long' in this case means 32 bit, not 64
                if (componentCount == 1)
                {
                    handler.SetInt32u(tagId, reader.GetUInt32(tagValueOffset));
                }
                else
                {
                    long[] array = new long[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        array[i] = reader.GetUInt32(tagValueOffset + (i * 4));
                    }
                    handler.SetInt32uArray(tagId, array);
                }
                break;
            }

            default:
            {
                handler.Error(Sharpen.Extensions.StringFormat("Unknown format code %d for tag %d", formatCode, tagId));
                break;
            }
            }
        }
Esempio n. 4
0
        private static void ProcessTag(Com.Drew.Metadata.Directory directory, int tagType, int tagValueOffset, int componentCount, int formatCode, RandomAccessReader reader)
        {
            switch (formatCode)
            {
            case FmtUndefined:
            {
                // Directory simply stores raw values
                // The display side uses a Descriptor class per directory to turn the raw values into 'pretty' descriptions
                // this includes exif user comments
                directory.SetByteArray(tagType, reader.GetBytes(tagValueOffset, componentCount));
                break;
            }

            case FmtString:
            {
                string @string = reader.GetNullTerminatedString(tagValueOffset, componentCount);
                directory.SetString(tagType, @string);
                break;
            }

            case FmtSrational:
            {
                if (componentCount == 1)
                {
                    directory.SetRational(tagType, new Rational(reader.GetInt32(tagValueOffset), reader.GetInt32(tagValueOffset + 4)));
                }
                else
                {
                    if (componentCount > 1)
                    {
                        Rational[] rationals = new Rational[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            rationals[i] = new Rational(reader.GetInt32(tagValueOffset + (8 * i)), reader.GetInt32(tagValueOffset + 4 + (8 * i)));
                        }
                        directory.SetRationalArray(tagType, rationals);
                    }
                }
                break;
            }

            case FmtUrational:
            {
                if (componentCount == 1)
                {
                    directory.SetRational(tagType, new Rational(reader.GetUInt32(tagValueOffset), reader.GetUInt32(tagValueOffset + 4)));
                }
                else
                {
                    if (componentCount > 1)
                    {
                        Rational[] rationals = new Rational[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            rationals[i] = new Rational(reader.GetUInt32(tagValueOffset + (8 * i)), reader.GetUInt32(tagValueOffset + 4 + (8 * i)));
                        }
                        directory.SetRationalArray(tagType, rationals);
                    }
                }
                break;
            }

            case FmtSingle:
            {
                if (componentCount == 1)
                {
                    directory.SetFloat(tagType, reader.GetFloat32(tagValueOffset));
                }
                else
                {
                    float[] floats = new float[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        floats[i] = reader.GetFloat32(tagValueOffset + (i * 4));
                    }
                    directory.SetFloatArray(tagType, floats);
                }
                break;
            }

            case FmtDouble:
            {
                if (componentCount == 1)
                {
                    directory.SetDouble(tagType, reader.GetDouble64(tagValueOffset));
                }
                else
                {
                    double[] doubles = new double[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        doubles[i] = reader.GetDouble64(tagValueOffset + (i * 4));
                    }
                    directory.SetDoubleArray(tagType, doubles);
                }
                break;
            }

            case FmtSbyte:
            {
                //
                // Note that all integral types are stored as int32 internally (the largest supported by TIFF)
                //
                if (componentCount == 1)
                {
                    directory.SetInt(tagType, reader.GetInt8(tagValueOffset));
                }
                else
                {
                    int[] bytes = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        bytes[i] = reader.GetInt8(tagValueOffset + i);
                    }
                    directory.SetIntArray(tagType, bytes);
                }
                break;
            }

            case FmtByte:
            {
                if (componentCount == 1)
                {
                    directory.SetInt(tagType, reader.GetUInt8(tagValueOffset));
                }
                else
                {
                    int[] bytes = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        bytes[i] = reader.GetUInt8(tagValueOffset + i);
                    }
                    directory.SetIntArray(tagType, bytes);
                }
                break;
            }

            case FmtUshort:
            {
                if (componentCount == 1)
                {
                    int i = reader.GetUInt16(tagValueOffset);
                    directory.SetInt(tagType, i);
                }
                else
                {
                    int[] ints = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        ints[i] = reader.GetUInt16(tagValueOffset + (i * 2));
                    }
                    directory.SetIntArray(tagType, ints);
                }
                break;
            }

            case FmtSshort:
            {
                if (componentCount == 1)
                {
                    int i = reader.GetInt16(tagValueOffset);
                    directory.SetInt(tagType, i);
                }
                else
                {
                    int[] ints = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        ints[i] = reader.GetInt16(tagValueOffset + (i * 2));
                    }
                    directory.SetIntArray(tagType, ints);
                }
                break;
            }

            case FmtSlong:
            case FmtUlong:
            {
                // NOTE 'long' in this case means 32 bit, not 64
                if (componentCount == 1)
                {
                    int i = reader.GetInt32(tagValueOffset);
                    directory.SetInt(tagType, i);
                }
                else
                {
                    int[] ints = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        ints[i] = reader.GetInt32(tagValueOffset + (i * 4));
                    }
                    directory.SetIntArray(tagType, ints);
                }
                break;
            }

            default:
            {
                directory.AddError("Unknown format code " + formatCode + " for tag " + tagType);
                break;
            }
            }
        }