Esempio n. 1
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);
                }
        }
Esempio n. 2
0
        /// <summary>
        /// Writes the EXIF profile.
        /// </summary>
        /// <param name="exifProfile">The exif profile.</param>
        /// <exception cref="ImageFormatException">
        /// Thrown if the EXIF profile size exceeds the limit
        /// </exception>
        private void WriteExifProfile(ExifProfile exifProfile)
        {
            const int Max = 65533;

            byte[] data = exifProfile?.ToByteArray();
            if (data == null || data.Length == 0)
            {
                return;
            }

            if (data.Length > Max)
            {
                throw new ImageFormatException($"Exif profile size exceeds limit. nameof{Max}");
            }

            int length = data.Length + 2;

            this.buffer[0] = JpegConstants.Markers.XFF;
            this.buffer[1] = JpegConstants.Markers.APP1; // Application Marker
            this.buffer[2] = (byte)((length >> 8) & 0xFF);
            this.buffer[3] = (byte)(length & 0xFF);

            this.outputStream.Write(this.buffer, 0, 4);
            this.outputStream.Write(data, 0, data.Length);
        }
Esempio n. 3
0
        public void ConstructorImageMetaData()
        {
            ImageMetaData metaData = new ImageMetaData();

            ExifProfile   exifProfile   = new ExifProfile();
            ImageProperty imageProperty = new ImageProperty("name", "value");

            metaData.ExifProfile          = exifProfile;
            metaData.FrameDelay           = 42;
            metaData.HorizontalResolution = 4;
            metaData.VerticalResolution   = 2;
            metaData.Properties.Add(imageProperty);
            metaData.Quality        = 24;
            metaData.RepeatCount    = 1;
            metaData.DisposalMethod = DisposalMethod.RestoreToBackground;

            ImageMetaData clone = new ImageMetaData(metaData);

            Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray());
            Assert.Equal(42, clone.FrameDelay);
            Assert.Equal(4, clone.HorizontalResolution);
            Assert.Equal(2, clone.VerticalResolution);
            Assert.Equal(imageProperty, clone.Properties[0]);
            Assert.Equal(24, clone.Quality);
            Assert.Equal(1, clone.RepeatCount);
            Assert.Equal(DisposalMethod.RestoreToBackground, clone.DisposalMethod);
        }
            public void ShouldReturnEmptyArrayWhenEmpty()
            {
                var profile = new ExifProfile();

                var bytes = profile.ToByteArray();

                Assert.Empty(bytes);
            }
Esempio n. 5
0
            public void ShouldReturnEmptyArrayWhenEmpty()
            {
                var profile = new ExifProfile();

                var bytes = profile.ToByteArray();

                Assert.AreEqual(0, bytes.Length);
            }
Esempio n. 6
0
            public void ShouldReturnOriginalDataWhenNotParsed()
            {
                using (IMagickImage image = new MagickImage(Files.FujiFilmFinePixS1ProJPG))
                {
                    ExifProfile profile = image.GetExifProfile();

                    var bytes = profile.ToByteArray();
                    Assert.AreEqual(4706, bytes.Length);
                }
            }
Esempio n. 7
0
            public void ShouldExcludeEmptyStrings()
            {
                var profile = new ExifProfile();

                profile.SetValue(ExifTag.ImageDescription, string.Empty);

                var data = profile.ToByteArray();

                var result = ExifReader.Read(data);

                Assert.Empty(result.Values);
            }
Esempio n. 8
0
        /// <summary>
        /// Writes the encoded image to the stream.
        /// </summary>
        /// <param name="stream">The stream to write to.</param>
        /// <param name="exifProfile">The exif profile.</param>
        /// <param name="width">The width of the image.</param>
        /// <param name="height">The height of the image.</param>
        /// <param name="hasAlpha">Flag indicating, if a alpha channel is present.</param>
        public void WriteEncodedImageToStream(Stream stream, ExifProfile exifProfile, uint width, uint height, bool hasAlpha)
        {
            bool isVp8X = false;

            byte[] exifBytes = null;
            uint   riffSize  = 0;

            if (exifProfile != null)
            {
                isVp8X    = true;
                riffSize += ExtendedFileChunkSize;
                exifBytes = exifProfile.ToByteArray();
                riffSize += this.ExifChunkSize(exifBytes);
            }

            this.Finish();
            uint size = (uint)this.NumBytes();

            size++; // One byte extra for the VP8L signature.

            // Write RIFF header.
            uint pad = size & 1;

            riffSize += WebpConstants.TagSize + WebpConstants.ChunkHeaderSize + size + pad;
            this.WriteRiffHeader(stream, riffSize);

            // Write VP8X, header if necessary.
            if (isVp8X)
            {
                this.WriteVp8XHeader(stream, exifProfile, width, height, hasAlpha);
            }

            // Write magic bytes indicating its a lossless webp.
            stream.Write(WebpConstants.Vp8LMagicBytes);

            // Write Vp8 Header.
            BinaryPrimitives.WriteUInt32LittleEndian(this.scratchBuffer, size);
            stream.Write(this.scratchBuffer.AsSpan(0, 4));
            stream.WriteByte(WebpConstants.Vp8LHeaderMagicByte);

            // Write the encoded bytes of the image to the stream.
            this.WriteToStream(stream);
            if (pad == 1)
            {
                stream.WriteByte(0);
            }

            if (exifProfile != null)
            {
                this.WriteExifProfile(stream, exifBytes);
            }
        }
Esempio n. 9
0
        public void EmptyWriter()
        {
            var profile = new ExifProfile()
            {
                Parts = ExifParts.GpsTags
            };

            profile.SetValue(ExifTag.Copyright, "Copyright text");

            byte[] bytes = profile.ToByteArray();

            Assert.NotNull(bytes);
            Assert.Empty(bytes);
        }
Esempio n. 10
0
            public void ShouldExcludeNullValues()
            {
                var profile = new ExifProfile();

                profile.SetValue(ExifTag.ImageDescription, null);

                var data = profile.ToByteArray();

                var reader = new ExifReader();

                reader.Read(data);

                Assert.AreEqual(0, reader.Values.Count);
            }
Esempio n. 11
0
            public void ShouldExcludeNullValues()
            {
                var profile = new ExifProfile();

                profile.SetValue(ExifTag.ImageDescription, null);

                var data = profile.ToByteArray();

                var reader = new ExifReader();

                reader.Read(data);

                EnumerableAssert.IsEmpty(reader.Values);
            }
Esempio n. 12
0
            public void ShouldReturnEmptyArrayWhenAllValuesAreInvalid()
            {
                var bytes = new byte[] { 69, 120, 105, 102, 0, 0, 73, 73, 42, 0, 8, 0, 0, 0, 1, 0, 42, 1, 4, 0, 1, 0, 0, 0, 42, 0, 0, 0, 26, 0, 0, 0, 0, 0 };

                var profile = new ExifProfile(bytes);

                var unkownTag = new ExifTag <uint>((ExifTagValue)298);
                var value     = profile.GetValue <uint>(unkownTag);

                Assert.AreEqual(42U, value.GetValue());
                Assert.AreEqual("42", value.ToString());

                bytes = profile.ToByteArray();
                Assert.AreEqual(0, bytes.Length);
            }
Esempio n. 13
0
        public void TestArrayValueWithUnspecifiedSize()
        {
            // This images contains array in the exif profile that has zero components.
            Image <Rgba32> image = TestFile.Create(TestImages.Jpeg.Issues.InvalidCast520).CreateImage();

            ExifProfile profile = image.MetaData.ExifProfile;

            Assert.NotNull(profile);

            // Force parsing of the profile.
            Assert.Equal(24, profile.Values.Count);

            byte[] bytes = profile.ToByteArray();
            Assert.Equal(489, bytes.Length);
        }
Esempio n. 14
0
        public void ConstructorImageMetadata()
        {
            var metaData = new ImageMetadata();

            var exifProfile = new ExifProfile();

            metaData.ExifProfile          = exifProfile;
            metaData.HorizontalResolution = 4;
            metaData.VerticalResolution   = 2;

            ImageMetadata clone = metaData.DeepClone();

            Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray());
            Assert.Equal(4, clone.HorizontalResolution);
            Assert.Equal(2, clone.VerticalResolution);
        }
Esempio n. 15
0
        /// <summary>
        /// Writes the EXIF profile.
        /// </summary>
        /// <param name="exifProfile">The exif profile.</param>
        private void WriteExifProfile(ExifProfile exifProfile)
        {
            if (exifProfile is null || exifProfile.Values.Count == 0)
            {
                return;
            }

            const int MaxBytesApp1       = 65533; // 64k - 2 padding bytes
            const int MaxBytesWithExifId = 65527; // Max - 6 bytes for EXIF header.

            byte[] data = exifProfile.ToByteArray();

            if (data.Length == 0)
            {
                return;
            }

            // We can write up to a maximum of 64 data to the initial marker so calculate boundaries.
            int exifMarkerLength = ProfileResolver.ExifMarker.Length;
            int remaining        = exifMarkerLength + data.Length;
            int bytesToWrite     = remaining > MaxBytesApp1 ? MaxBytesApp1 : remaining;
            int app1Length       = bytesToWrite + 2;

            // Write the app marker, EXIF marker, and data
            this.WriteApp1Header(app1Length);
            this.outputStream.Write(ProfileResolver.ExifMarker);
            this.outputStream.Write(data, 0, bytesToWrite - exifMarkerLength);
            remaining -= bytesToWrite;

            // If the exif data exceeds 64K, write it in multiple APP1 Markers
            for (int idx = MaxBytesWithExifId; idx < data.Length; idx += MaxBytesWithExifId)
            {
                bytesToWrite = remaining > MaxBytesWithExifId ? MaxBytesWithExifId : remaining;
                app1Length   = bytesToWrite + 2 + exifMarkerLength;

                this.WriteApp1Header(app1Length);

                // Write Exif00 marker
                this.outputStream.Write(ProfileResolver.ExifMarker);

                // Write the exif data
                this.outputStream.Write(data, idx, bytesToWrite);

                remaining -= bytesToWrite;
            }
        }
Esempio n. 16
0
        public void IfdStructure()
        {
            var exif = new ExifProfile();

            exif.SetValue(ExifTag.XPAuthor, "Dan Petitt");

            Span <byte> actualBytes = exif.ToByteArray();

            // Assert
            int ifdOffset = ExifConstants.LittleEndianByteOrderMarker.Length;

            Assert.Equal(8U, BinaryPrimitives.ReadUInt32LittleEndian(actualBytes.Slice(ifdOffset, 4)));

            int nextIfdPointerOffset = ExifConstants.LittleEndianByteOrderMarker.Length + 4 + 2 + 12;

            Assert.Equal(0U, BinaryPrimitives.ReadUInt32LittleEndian(actualBytes.Slice(nextIfdPointerOffset, 4)));
        }
Esempio n. 17
0
        public void ConstructorImageMetaData()
        {
            var metaData = new ImageMetaData();

            var exifProfile   = new ExifProfile();
            var imageProperty = new ImageProperty("name", "value");

            metaData.ExifProfile          = exifProfile;
            metaData.HorizontalResolution = 4;
            metaData.VerticalResolution   = 2;
            metaData.Properties.Add(imageProperty);

            ImageMetaData clone = metaData.DeepClone();

            Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray());
            Assert.Equal(4, clone.HorizontalResolution);
            Assert.Equal(2, clone.VerticalResolution);
            Assert.Equal(imageProperty, clone.Properties[0]);
        }
Esempio n. 18
0
        public void Test_UnknownExifTag()
        {
            var exifProfile = new ExifProfile();

            exifProfile.SetValue(ExifTag.ImageWidth, 42);

            var bytes = exifProfile.ToByteArray();

            bytes[16] = 42;

            exifProfile = new ExifProfile(bytes);

            ExifTag   unkownTag = (ExifTag)298;
            ExifValue value     = exifProfile.GetValue(unkownTag);

            Assert.AreEqual(42, value.Value);
            Assert.AreEqual("42", value.ToString());

            bytes = exifProfile.ToByteArray();
            Assert.AreEqual(0, bytes.Length);
        }
Esempio n. 19
0
        public void ConstructorImageMetaData()
        {
            ImageMetaData metaData = new ImageMetaData();

            ExifProfile   exifProfile   = new ExifProfile();
            ImageProperty imageProperty = new ImageProperty("name", "value");

            metaData.ExifProfile          = exifProfile;
            metaData.HorizontalResolution = 4;
            metaData.VerticalResolution   = 2;
            metaData.Properties.Add(imageProperty);
            metaData.RepeatCount = 1;

            ImageMetaData clone = new ImageMetaData(metaData);

            Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray());
            Assert.Equal(4, clone.HorizontalResolution);
            Assert.Equal(2, clone.VerticalResolution);
            Assert.Equal(imageProperty, clone.Properties[0]);
            Assert.Equal(1, clone.RepeatCount);
        }
Esempio n. 20
0
            public void ShouldReturnEmptyArrayWhenAllValuesAreInvalid()
            {
                var profile = new ExifProfile();

                profile.SetValue(ExifTag.ImageWidth, 42);

                var bytes = profile.ToByteArray();

                bytes[16] = 42;

                profile = new ExifProfile(bytes);

                var unkownTag = (ExifTag)298;
                var value     = profile.GetValue(unkownTag);

                Assert.AreEqual(42, value.Value);
                Assert.AreEqual("42", value.ToString());

                bytes = profile.ToByteArray();
                Assert.AreEqual(0, bytes.Length);
            }
Esempio n. 21
0
        public void TestArrayValueWithUnspecifiedSize()
        {
            // This images contains array in the exif profile that has zero components.
            using Image <Rgba32> image = TestFile.Create(TestImages.Jpeg.Issues.InvalidCast520).CreateRgba32Image();

            ExifProfile profile = image.Metadata.ExifProfile;

            Assert.NotNull(profile);

            // Force parsing of the profile.
            Assert.Equal(25, profile.Values.Count);

            // todo: duplicate tags (from root container and subIfd)
            Assert.Equal(2, profile.Values.Count(v => (ExifTagValue)(ushort)v.Tag == ExifTagValue.DateTime));

            byte[] bytes = profile.ToByteArray();
            Assert.Equal(525, bytes.Length);

            var profile2 = new ExifProfile(bytes);

            Assert.Equal(25, profile2.Values.Count);
        }
Esempio n. 22
0
        public void ProfileToByteArray()
        {
            // arrange
            byte[]      exifBytesWithoutExifCode = ExifConstants.LittleEndianByteOrderMarker;
            ExifProfile expectedProfile          = CreateExifProfile();
            var         expectedProfileTags      = expectedProfile.Values.Select(x => x.Tag).ToList();

            // act
            byte[] actualBytes   = expectedProfile.ToByteArray();
            var    actualProfile = new ExifProfile(actualBytes);

            // assert
            Assert.NotNull(actualBytes);
            Assert.NotEmpty(actualBytes);
            Assert.Equal(exifBytesWithoutExifCode, actualBytes.Take(exifBytesWithoutExifCode.Length).ToArray());
            foreach (ExifTag expectedProfileTag in expectedProfileTags)
            {
                ExifValue actualProfileValue   = actualProfile.GetValue(expectedProfileTag);
                ExifValue expectedProfileValue = expectedProfile.GetValue(expectedProfileTag);
                Assert.Equal(expectedProfileValue.Value, actualProfileValue.Value);
            }
        }
Esempio n. 23
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.Mutate(x => x.AutoOrient());
            }
        }