Пример #1
0
        /// <summary>
        /// Set exif data to Jpeg file; It blocks thread.
        /// Mess of this library; everything are caused by crazy Exif format.
        /// Note that this function overwrites ALL Exif data in the given image.
        /// </summary>
        /// <param name="OriginalImage">Target image</param>
        /// <param name="MetaData">An Exif data which will be added to the image.</param>
        /// <returns>New image</returns>
        public static byte[] SetMetaData(byte[] OriginalImage, JpegMetaData MetaData)
        {
            var OriginalMetaData = JpegMetaDataParser.ParseImage(OriginalImage);
            // Debug.WriteLine("Original image size: " + OriginalImage.Length.ToString("X"));

            // It seems there's a bug handling little endian jpeg image on WP OS.
            var OutputImageMetadataEndian = Definitions.Endian.Big;

            var App0Offset = 0;

            if (Util.GetUIntValue(OriginalImage, 2, 2, Definitions.Endian.Big) == Definitions.APP0_MARKER)
            {
                App0Offset = 2 + (int)Util.GetUIntValue(OriginalImage, 4, 2, Definitions.Endian.Big);
                // Debug.WriteLine("APP0 marker detected. " + App0Offset);
            }

            // Note: App1 size and ID are fixed to Big endian.
            UInt32 OriginalApp1DataSize = Util.GetUIntValue(OriginalImage, 4 + App0Offset, 2, Definitions.Endian.Big);
            // Debug.WriteLine("Original App1 size: " + OriginalApp1DataSize.ToString("X"));

            // 0-5 byte: Exif identify code. E, x, i, f, \0, \0
            // 6-13 byte: TIFF header. endian, 0x002A, Offset to Primary IFD in 4 bytes. generally, 8 is set as the offset.
            var OriginalApp1Data = new byte[OriginalApp1DataSize];

            Array.Copy(OriginalImage, 6 + App0Offset, OriginalApp1Data, 0, (int)OriginalApp1DataSize);

            var NewApp1Data = CreateApp1Data(OriginalMetaData, MetaData, OriginalApp1Data, OutputImageMetadataEndian);

            // Only size of App1 data is different.
            var NewImage = new byte[OriginalImage.Length - OriginalApp1DataSize + NewApp1Data.Length];
            // Debug.WriteLine("New image size: " + NewImage.Length.ToString("X"));

            // Copy SOI, App1 marker
            var newImageHeader = new byte[4] {
                0xFF, 0xD8, 0xFF, 0xE1
            };

            Array.Copy(newImageHeader, 0, NewImage, 0, 2 + 2);

            // Important note again: App 1 data size is stored in Big endian.
            var App1SizeData = Util.ToByte((UInt32)NewApp1Data.Length, 2, Definitions.Endian.Big);

            Array.Copy(App1SizeData, 0, NewImage, 4, 2);

            // After that, copy App1 data to new image.
            Array.Copy(NewApp1Data, 0, NewImage, 6, NewApp1Data.Length);

            // At last, copy body from original image.
            Array.Copy(OriginalImage, 2 + 2 + 2 + App0Offset + (int)OriginalApp1DataSize, NewImage, 2 + 2 + 2 + NewApp1Data.Length, OriginalImage.Length - 2 - 2 - 2 - App0Offset - (int)OriginalApp1DataSize);

            return(NewImage);
        }
Пример #2
0
        public void OverwriteGeotag()
        {
            var task = WaitLocation();

            task.Wait();
            var position = task.Result;

            Debug.WriteLine("pos: " + position.Coordinate.Longitude + " " + position.Coordinate.Latitude);
            var mediaLibrary = new MediaLibrary();

            int count = 0;

            foreach (string filename in TestFiles.ValidImages)
            {
                var image            = TestUtil.GetResourceByteArray(filename);
                var originalMetadata = JpegMetaDataParser.ParseImage(image);
                var NewImage         = MetaDataOperator.AddGeoposition(image, position, true);
                var newMetadata      = JpegMetaDataParser.ParseImage(NewImage);

                try
                {
                    var pic = mediaLibrary.SavePicture(string.Format("Exif addition test_" + count + "_{0:yyyyMMdd_HHmmss}.jpg", DateTime.Now), NewImage);
                }
                catch (NullReferenceException) { }

                GC.Collect();
                TestUtil.IsGpsDataAdded(originalMetadata, newMetadata);

                using (var imageStream = TestUtil.GetResourceStream(filename))
                {
                    originalMetadata = JpegMetaDataParser.ParseImage(imageStream);
                    var newImageStream = MetaDataOperator.AddGeoposition(imageStream, position, true);
                    try
                    {
                        var pic2 = mediaLibrary.SavePicture(string.Format("Exif addition test_" + count + "_stream_{0:yyyyMMdd_HHmmss}.jpg", DateTime.Now), newImageStream);
                    }
                    catch (NullReferenceException) { }
                    finally { newImageStream.Dispose(); }
                    TestUtil.IsGpsDataAdded(originalMetadata, newMetadata);

                    count++;
                }


                GC.Collect(); // Saving many big images in short time, memory mey be run out and it may throws NullReferenceException or OutOfMemoryException.
            }
        }
Пример #3
0
        public override async Task <Tuple <BitmapImage, JpegMetaData> > PlaybackStillImage(Thumbnail content)
        {
            using (var stream = await content.CacheFile.OpenStreamForReadAsync())
            {
                var bitmap = new BitmapImage();
                await bitmap.SetSourceAsync(stream.AsRandomAccessStream());

                try
                {
                    var meta = await JpegMetaDataParser.ParseImageAsync(stream);

                    return(Tuple.Create(bitmap, meta));
                }
                catch (UnsupportedFileFormatException)
                {
                    return(Tuple.Create <BitmapImage, JpegMetaData>(bitmap, null));
                }
            }
        }
Пример #4
0
        public override async Task <Tuple <BitmapImage, JpegMetaData> > PlaybackStillImage(Thumbnail content)
        {
            using (var res = await HttpClient.GetAsync(new Uri(content.Source.LargeUrl)))
            {
                if (!res.IsSuccessStatusCode)
                {
                    throw new IOException();
                }

                var buff = await res.Content.ReadAsBufferAsync();

                using (var stream = new InMemoryRandomAccessStream())
                {
                    await stream.WriteAsync(buff); // Copy to the new stream to avoid stream crash issue.

                    if (stream.Size == 0)
                    {
                        throw new IOException();
                    }
                    stream.Seek(0);

                    var bitmap = new BitmapImage();
                    await bitmap.SetSourceAsync(stream);

                    try
                    {
                        var meta = await JpegMetaDataParser.ParseImageAsync(stream.AsStream());

                        return(Tuple.Create(bitmap, meta));
                    }
                    catch (UnsupportedFileFormatException)
                    {
                        return(Tuple.Create <BitmapImage, JpegMetaData>(bitmap, null));
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Set exif data to Jpeg file; It blocks thread.
        /// Mess of this library; everything are caused by crazy Exif format.
        /// Note that this function overwrites ALL Exif data in the given image.
        /// </summary>
        /// <param name="OriginalImage">Target image. This will be disposed.</param>
        /// <param name="MetaData">An Exif data which will be added to the image.</param>
        /// <returns>New image on new stream.</returns>
        public static Stream SetMetaData(Stream OriginalImage, JpegMetaData MetaData)
        {
            OriginalImage.Seek(0, SeekOrigin.Begin);

            var OriginalMetaData          = JpegMetaDataParser.ParseImage(OriginalImage);
            var OutputImageMetaDataEndian = Definitions.Endian.Big;

            var endian = Definitions.Endian.Big;

            OriginalImage.Position = 2;
            var FirstMarker = new byte[2];

            OriginalImage.Read(FirstMarker, 0, 2);
            var App0Offset = 0;

            if (Util.GetUIntValue(FirstMarker, 0, 2, endian) == Definitions.APP0_MARKER)
            {
                var App0SizeData = new byte[2];
                OriginalImage.Read(App0SizeData, 0, 2);
                App0Offset = 2 + (int)Util.GetUIntValue(App0SizeData, 0, 2, endian);
            }

            OriginalImage.Position = 4 + App0Offset;
            var app1sizeData = new byte[2];

            OriginalImage.Read(app1sizeData, 0, 2);

            var OriginalApp1Size = Util.GetUIntValue(app1sizeData, 0, 2, endian);

            OriginalImage.Position = 6 + App0Offset;

            var OriginalApp1Data = new byte[OriginalApp1Size];

            OriginalImage.Read(OriginalApp1Data, 0, (int)OriginalApp1Size);

            var NewApp1Data = CreateApp1Data(OriginalMetaData, MetaData, OriginalApp1Data, OutputImageMetaDataEndian);

            // first 6 bytes;
            var NewImageHeader = new byte[6] {
                0xFF, 0xD8, 0xFF, 0xE1, 0x0, 0x0
            };                                                                     // No APP0 section will be stored on new image.

            // Important note again: App 1 data size is stored in Big endian.
            var App1SizeData = Util.ToByte((UInt32)NewApp1Data.Length, 2, Definitions.Endian.Big);

            Array.Copy(App1SizeData, 0, NewImageHeader, 4, 2);

            Util.DumpByteArrayAll(NewImageHeader);

            var NewImage = new MemoryStream();

            NewImage.Write(NewImageHeader, 0, 6);

            NewImage.Write(NewApp1Data, 0, NewApp1Data.Length);

            // forward pointer to start position of original body data
            OriginalImage.Position = 6 + App0Offset + OriginalApp1Size;

            // Copy all other data from original image.
            int BufSize = 4096;

            byte[] buffer = new byte[BufSize];
            int    numBytes;
            int    count = 0;

            while ((numBytes = OriginalImage.Read(buffer, 0, BufSize)) > 0)
            {
                NewImage.Write(buffer, 0, numBytes);
                count += numBytes;
            }

            NewImage.Seek(0, SeekOrigin.Begin);

            // Debug.WriteLine("image size: " + NewImage.Length);
            OriginalImage.Dispose();
            return(NewImage);
        }