Ejemplo n.º 1
0
 public ExifByte(ExifTag <byte> tag, ExifDataType dataType)
     : base(tag) => this.DataType = dataType;
Ejemplo n.º 2
0
        private object ConvertValue(ExifDataType dataType, ReadOnlySpan <byte> buffer, uint numberOfComponents)
        {
            if (buffer.Length == 0)
            {
                return(null);
            }

            switch (dataType)
            {
            case ExifDataType.Unknown:
                return(null);

            case ExifDataType.Ascii:
                return(this.ConvertToString(buffer));

            case ExifDataType.Byte:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToByte(buffer));
                }

                return(buffer.ToArray());

            case ExifDataType.DoubleFloat:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToDouble(buffer));
                }

                return(ToArray(dataType, buffer, this.ConvertToDouble));

            case ExifDataType.Long:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToUInt32(buffer));
                }

                return(ToArray(dataType, buffer, this.ConvertToUInt32));

            case ExifDataType.Rational:
                if (numberOfComponents == 1)
                {
                    return(this.ToRational(buffer));
                }

                return(ToArray(dataType, buffer, this.ToRational));

            case ExifDataType.Short:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToShort(buffer));
                }

                return(ToArray(dataType, buffer, this.ConvertToShort));

            case ExifDataType.SignedByte:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToSignedByte(buffer));
                }

                return(ToArray(dataType, buffer, this.ConvertToSignedByte));

            case ExifDataType.SignedLong:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToInt32(buffer));
                }

                return(ToArray(dataType, buffer, this.ConvertToInt32));

            case ExifDataType.SignedRational:
                if (numberOfComponents == 1)
                {
                    return(this.ToSignedRational(buffer));
                }

                return(ToArray(dataType, buffer, this.ToSignedRational));

            case ExifDataType.SignedShort:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToSignedShort(buffer));
                }

                return(ToArray(dataType, buffer, this.ConvertToSignedShort));

            case ExifDataType.SingleFloat:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToSingle(buffer));
                }

                return(ToArray(dataType, buffer, this.ConvertToSingle));

            case ExifDataType.Undefined:
                if (numberOfComponents == 1)
                {
                    return(this.ConvertToByte(buffer));
                }

                return(buffer.ToArray());

            default:
                throw new NotSupportedException();
            }
        }
Ejemplo n.º 3
0
        private static object ParseValue(ExifId id, ExifDataType type, byte[] data)
        {
            if (type != ExifDataType.Binary && type != ExifDataType.Undefined)
            {
                if (data == null)
                    throw new ArgumentNullException(nameof(data), String.Format("ID: {0}. Type: {1}.", id, type));
            }

            object temp;
            if (SpecialParseValue(id, type, data, out temp))
                return temp;

            switch (type)
            {
                case ExifDataType.Binary:
                    return data;
                case ExifDataType.ASCII:
                    return Encoding.ASCII.GetString(data).RemoveNullChars();
                case ExifDataType.Int16:
                    return BitConverter.ToInt16(data, 0);
                case ExifDataType.Int32:
                    return BitConverter.ToInt32(data, 0);
                case ExifDataType.Long:
                    return BitConverter.ToInt64(data, 0);
                case ExifDataType.Float:
                case ExifDataType.Double:
                    return (double)BitConverter.ToInt32(data, 0) / (double)BitConverter.ToInt32(data, 4);
                case ExifDataType.Undefined:
                    return data;

                default:
                    throw new NotImplementedException(String.Format("Type not implemented: {0}", type));
            }
        }
Ejemplo n.º 4
0
        private static bool SpecialParseValue(ExifId id, ExifDataType type, byte[] data, out object temp)
        {
            temp = null;

            switch (id)
            {
                // Convert to DateTime
                case ExifId.ImageDateTime:
                case ExifId.ImageDateTimeOriginal:
                case ExifId.ImagePreviewDateTime:
                case ExifId.PhotoDateTimeDigitized:
                //case ExifId.PhotoDateTimeOriginal: // Same value as ImageDateTimeOriginal
                case ExifId.ThumbnailDateTime:
                    string datestring = Encoding.ASCII.GetString(data).RemoveNullChars();
                    DateTime datetime;
                    if (DateTime.TryParse(datestring, out datetime))
                    {
                        temp = datetime;
                        return true;
                    }

                    // Handle special cases
                    if (DateTime.TryParseExact(datestring, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out datetime))
                    {
                        temp = datetime;
                        return true;
                    }
                    return false;

                // Convert to UCS-2
                case ExifId.ImageXPAuthor:
                case ExifId.ImageXPComment:
                case ExifId.ImageXPSubject:
                case ExifId.ImageXPTitle:
                    temp = Encoding.GetEncoding("ucs-2").GetString(data).RemoveNullChars();
                    return true;
                case ExifId.ImageXPKeywords:
                    string keywords = Encoding.GetEncoding("ucs-2").GetString(data).RemoveNullChars();
                    if (keywords.Length > 0)
                        temp = keywords.Split(new char[] { TagsSeparator }, StringSplitOptions.RemoveEmptyEntries);
                    else
                        temp = new string[0];
                    return true;

                default:
                    return false;
            }
        }
Ejemplo n.º 5
0
        private object ConvertValue(ExifDataType dataType, uint length, uint numberOfComponents)
        {
            if (length == 0)
            {
                return(null);
            }

            switch (dataType)
            {
            case ExifDataType.Unknown:
                return(null);

            case ExifDataType.Ascii:
                return(ReadString(length));

            case ExifDataType.Undefined:
            case ExifDataType.Byte:
                if (numberOfComponents == 1)
                {
                    return(ReadByte());
                }
                else
                {
                    return(ToArray(dataType, length, ReadByte));
                }

            case ExifDataType.DoubleFloat:
                if (numberOfComponents == 1)
                {
                    return(ReadDouble());
                }
                else
                {
                    return(ToArray(dataType, length, ReadDouble));
                }

            case ExifDataType.Long:
                if (numberOfComponents == 1)
                {
                    return(ReadLong());
                }
                else
                {
                    return(ToArray(dataType, length, ReadLong));
                }

            case ExifDataType.Rational:
                if (numberOfComponents == 1)
                {
                    return(ReadRational());
                }
                else
                {
                    return(ToArray(dataType, length, ReadRational));
                }

            case ExifDataType.Short:
                if (numberOfComponents == 1)
                {
                    return(ReadShort());
                }
                else
                {
                    return(ToArray(dataType, length, ReadShort));
                }

            case ExifDataType.SignedByte:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedByte());
                }
                else
                {
                    return(ToArray(dataType, length, ReadSignedByte));
                }

            case ExifDataType.SignedLong:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedLong());
                }
                else
                {
                    return(ToArray(dataType, length, ReadSignedLong));
                }

            case ExifDataType.SignedRational:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedRational());
                }
                else
                {
                    return(ToArray(dataType, length, ReadSignedRational));
                }

            case ExifDataType.SignedShort:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedShort());
                }
                else
                {
                    return(ToArray(dataType, length, ReadSignedShort));
                }

            case ExifDataType.SingleFloat:
                if (numberOfComponents == 1)
                {
                    return(ReadSingle());
                }
                else
                {
                    return(ToArray(dataType, length, ReadSingle));
                }

            default:
                throw new NotSupportedException();
            }
        }
Ejemplo n.º 6
0
 internal ExifValue(ExifTag tag, ExifDataType dataType)
 {
     Tag      = tag;
     DataType = dataType;
 }
Ejemplo n.º 7
0
 private int WriteValue(ExifDataType dataType, object value, byte[] destination, int offset)
 {
   switch (dataType)
   {
     case ExifDataType.Ascii:
       return Write(Encoding.UTF8.GetBytes((string)value), destination, offset);
     case ExifDataType.Byte:
     case ExifDataType.Undefined:
       destination[offset] = (byte)value;
       return offset + 1;
     case ExifDataType.DoubleFloat:
       return Write(BitConverter.GetBytes((double)value), destination, offset);
     case ExifDataType.Short:
       return Write(BitConverter.GetBytes((ushort)value), destination, offset);
     case ExifDataType.Long:
       return Write(BitConverter.GetBytes((uint)value), destination, offset);
     case ExifDataType.Rational:
       return WriteRational((double)value, destination, offset);
     case ExifDataType.SignedByte:
       destination[offset] = unchecked((byte)((sbyte)value));
       return offset + 1;
     case ExifDataType.SignedLong:
       return Write(BitConverter.GetBytes((int)value), destination, offset);
     case ExifDataType.SignedShort:
       return Write(BitConverter.GetBytes((short)value), destination, offset);
     case ExifDataType.SignedRational:
       return WriteSignedRational((double)value, destination, offset);
     case ExifDataType.SingleFloat:
       return Write(BitConverter.GetBytes((float)value), destination, offset);
     default:
       throw new NotImplementedException();
   }
 }
Ejemplo n.º 8
0
        public void AutoOrient_WorksWithCorruptExifData <TPixel>(TestImageProvider <TPixel> provider, ExifDataType dataType, byte[] orientation)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            var profile = new ExifProfile();

            profile.SetValue(ExifTag.JPEGTables, orientation);

            byte[] bytes = profile.ToByteArray();

            // Change the tag into ExifTag.Orientation
            bytes[16] = 18;
            bytes[17] = 1;

            // Change the data type
            bytes[18] = (byte)dataType;

            // Change the number of components
            bytes[20] = 1;

            var orientationCodeData = new byte[8];

            Array.Copy(orientation, orientationCodeData, orientation.Length);

            ulong orientationCode = BitConverter.ToUInt64(orientationCodeData, 0);

            using (Image <TPixel> image = provider.GetImage())
                using (Image <TPixel> reference = image.Clone())
                {
                    image.Metadata.ExifProfile = new ExifProfile(bytes);
                    image.Mutate(x => x.AutoOrient());
                    image.DebugSave(provider, $"{dataType}-{orientationCode}", appendPixelTypeToFileName: false);
                    ImageComparer.Exact.VerifySimilarity(image, reference);
                }
        }
Ejemplo n.º 9
0
        private object ReadValue(ExifDataType dataType, uint numberOfComponents)
        {
            switch (dataType)
            {
            case ExifDataType.Byte:
            case ExifDataType.Undefined:
                if (numberOfComponents == 1)
                {
                    return(ReadByte());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadByte));
                }

            case ExifDataType.Double:
                if (numberOfComponents == 1)
                {
                    return(ReadDouble());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadDouble));
                }

            case ExifDataType.Float:

                if (numberOfComponents == 1)
                {
                    return(ReadFloat());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadFloat));
                }

            case ExifDataType.Long:
                if (numberOfComponents == 1)
                {
                    return(ReadLong());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadLong));
                }

            case ExifDataType.Rational:
                if (numberOfComponents == 1)
                {
                    return(ReadRational());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadRational));
                }

            case ExifDataType.Short:
                if (numberOfComponents == 1)
                {
                    return(ReadShort());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadShort));
                }

            case ExifDataType.SignedByte:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedByte());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadSignedByte));
                }

            case ExifDataType.SignedLong:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedLong());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadSignedLong));
                }

            case ExifDataType.SignedRational:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedRational());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadSignedRational));
                }

            case ExifDataType.SignedShort:
                if (numberOfComponents == 1)
                {
                    return(ReadSignedShort());
                }
                else
                {
                    return(ReadArray(numberOfComponents, ReadSignedShort));
                }

            case ExifDataType.String:
                return(ReadString(numberOfComponents));

            default:
                throw new NotSupportedException();
            }
        }
Ejemplo n.º 10
0
 public static ExifValue Create(ExifTagValue tag, ExifDataType dataType, ulong numberOfComponents) => Create(tag, dataType, numberOfComponents != 1);
Ejemplo n.º 11
0
 internal static ExifByte Create(ExifTag tag, ExifDataType dataType, byte value) => new ExifByte(tag, dataType)
 {
     Value = value
 };
Ejemplo n.º 12
0
 internal ExifByte(ExifTag tag, ExifDataType dataType)
     : base(tag, dataType)
 {
 }
Ejemplo n.º 13
0
        private bool TryReadValue(out ExifValue exifValue)
        {
            exifValue = default;

            // 2   | 2    | 4     | 4
            // tag | type | count | value offset
            if (this.RemainingLength < 12)
            {
                return(false);
            }

            var          tag      = (ExifTagValue)this.ReadUInt16();
            ExifDataType dataType = EnumUtils.Parse(this.ReadUInt16(), ExifDataType.Unknown);

            // Ensure that the data type is valid
            if (dataType == ExifDataType.Unknown)
            {
                return(false);
            }

            uint numberOfComponents = this.ReadUInt32();

            // Issue #132: ExifDataType == Undefined is treated like a byte array.
            // If numberOfComponents == 0 this value can only be handled as an inline value and must fallback to 4 (bytes)
            if (dataType == ExifDataType.Undefined && numberOfComponents == 0)
            {
                numberOfComponents = 4;
            }

            uint size = numberOfComponents * ExifDataTypes.GetSize(dataType);

            this.TryReadSpan(4, out ReadOnlySpan <byte> offsetBuffer);

            object value;

            if (size > 4)
            {
                int  oldIndex = this.position;
                uint newIndex = this.ConvertToUInt32(offsetBuffer);

                // Ensure that the new index does not overrun the data
                if (newIndex > int.MaxValue)
                {
                    this.AddInvalidTag(new UnkownExifTag(tag));
                    return(false);
                }

                this.position = (int)newIndex;

                if (this.RemainingLength < size)
                {
                    this.AddInvalidTag(new UnkownExifTag(tag));

                    this.position = oldIndex;
                    return(false);
                }

                this.TryReadSpan((int)size, out ReadOnlySpan <byte> dataBuffer);

                value         = this.ConvertValue(dataType, dataBuffer, numberOfComponents);
                this.position = oldIndex;
            }
            else
            {
                value = this.ConvertValue(dataType, offsetBuffer, numberOfComponents);
            }

            exifValue = ExifValues.Create(tag) ?? ExifValues.Create(tag, dataType, numberOfComponents);

            if (exifValue is null)
            {
                this.AddInvalidTag(new UnkownExifTag(tag));
                return(false);
            }

            if (!exifValue.TrySetValue(value))
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 14
0
 public ExifByteArray(ExifTag <byte[]> tag, ExifDataType dataType)
     : base(tag) => DataType = dataType;
Ejemplo n.º 15
0
 internal ExifValue(ExifTag tag, ExifDataType dataType, object value, bool isArray)
     : this(tag, dataType, isArray)
 {
     _value = value;
 }
Ejemplo n.º 16
0
        private object ConvertValue(ExifDataType dataType, byte[] data, uint numberOfComponents)
        {
            if (data == null || data.Length == 0)
            {
                return(null);
            }

            switch (dataType)
            {
            case ExifDataType.Unknown:
                return(null);

            case ExifDataType.Ascii:
                return(ToString(data));

            case ExifDataType.Byte:
                if (numberOfComponents == 1)
                {
                    return(ToByte(data));
                }
                else
                {
                    return(data);
                }

            case ExifDataType.DoubleFloat:
                if (numberOfComponents == 1)
                {
                    return(ToDouble(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToDouble));
                }

            case ExifDataType.Long:
                if (numberOfComponents == 1)
                {
                    return(ToLong(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToLong));
                }

            case ExifDataType.Rational:
                if (numberOfComponents == 1)
                {
                    return(ToRational(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToRational));
                }

            case ExifDataType.Short:
                if (numberOfComponents == 1)
                {
                    return(ToShort(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToShort));
                }

            case ExifDataType.SignedByte:
                if (numberOfComponents == 1)
                {
                    return(ToSignedByte(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToSignedByte));
                }

            case ExifDataType.SignedLong:
                if (numberOfComponents == 1)
                {
                    return(ToSignedLong(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToSignedLong));
                }

            case ExifDataType.SignedRational:
                if (numberOfComponents == 1)
                {
                    return(ToSignedRational(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToSignedRational));
                }

            case ExifDataType.SignedShort:
                if (numberOfComponents == 1)
                {
                    return(ToSignedShort(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToSignedShort));
                }

            case ExifDataType.SingleFloat:
                if (numberOfComponents == 1)
                {
                    return(ToSingle(data));
                }
                else
                {
                    return(ToArray(dataType, data, ToSingle));
                }

            case ExifDataType.Undefined:
                if (numberOfComponents == 1)
                {
                    return(ToByte(data));
                }
                else
                {
                    return(data);
                }

            default:
                throw new NotSupportedException();
            }
        }
Ejemplo n.º 17
0
        public void ImageShouldAutoRotateInvalidValues <TPixel>(TestImageProvider <TPixel> provider, ExifDataType dataType, byte[] orientation)
            where TPixel : struct, IPixel <TPixel>
        {
            var profile = new ExifProfile();

            profile.SetValue(ExifTag.JPEGTables, orientation);

            byte[] bytes = profile.ToByteArray();
            // Change the tag into ExifTag.Orientation
            bytes[16] = 18;
            bytes[17] = 1;
            // Change the data type
            bytes[18] = (byte)dataType;
            // Change the number of components
            bytes[20] = 1;

            using (Image <TPixel> image = provider.GetImage())
            {
                image.MetaData.ExifProfile = new ExifProfile(bytes);
                image.AutoOrient();
            }
        }