Exemple #1
0
        private void CreateAndShowMainWindow()
        {
            // Create the application's main window
            mainWindow       = new Window();
            mainWindow.Title = "Image Metadata";

            // <SnippetSetQuery>
            Stream                      pngStream  = new System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            PngBitmapDecoder            pngDecoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            BitmapFrame                 pngFrame   = pngDecoder.Frames[0];
            InPlaceBitmapMetadataWriter pngInplace = pngFrame.CreateInPlaceBitmapMetadataWriter();

            if (pngInplace.TrySave() == true)
            {
                pngInplace.SetQuery("/Text/Description", "Have a nice day.");
            }
            pngStream.Close();
            // </SnippetSetQuery>

            // Draw the Image
            Image myImage = new Image();

            myImage.Source  = new BitmapImage(new Uri("smiley.png", UriKind.Relative));
            myImage.Stretch = Stretch.None;
            myImage.Margin  = new Thickness(20);

            // <SnippetGetQuery>

            // Add the metadata of the bitmap image to the text block.
            TextBlock myTextBlock = new TextBlock();

            myTextBlock.Text = "The Description metadata of this image is: " + pngInplace.GetQuery("/Text/Description").ToString();
            // </SnippetGetQuery>

            // Define a StackPanel to host Controls
            StackPanel myStackPanel = new StackPanel();

            myStackPanel.Orientation         = Orientation.Vertical;
            myStackPanel.Height              = 200;
            myStackPanel.VerticalAlignment   = VerticalAlignment.Top;
            myStackPanel.HorizontalAlignment = HorizontalAlignment.Center;

            // Add the Image and TextBlock to the parent Grid
            myStackPanel.Children.Add(myImage);
            myStackPanel.Children.Add(myTextBlock);

            // Add the StackPanel as the Content of the Parent Window Object
            mainWindow.Content = myStackPanel;
            mainWindow.Show();
        }
    public static void SetImageMetadata(string imagesFolderPath)
    {
        string originalPath = @"C:\Users\test\Desktop\test.jpg";
        string outputPath   = Environment.CurrentDirectory + @"\output.jpg";
        string finalPath    = Environment.CurrentDirectory + @"\output_beforeInPlaceBitmapMetadataWriter.jpg";
        BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile;
        uint paddingAmount = 2048;     // 2Kb padding for this example, but really this can be any value.

        // Our recommendation is to keep this between 1Kb and 5Kb as most metadata updates are not large.
        // High level overview:
        //   1. Perform a lossles transcode on the JPEG
        //   2. Add appropriate padding
        //   3. Optionally add whatever metadata we need to add initially
        //   4. Save the file
        //   5. For sanity, we verify that we really did a lossless transcode
        //   6. Open the new file and add metadata in-place
        using (Stream originalFile = File.Open(originalPath, FileMode.Open, FileAccess.Read))
        {
            // Notice the BitmapCreateOptions and BitmapCacheOption. Using these options in the manner here
            // will inform the JPEG decoder and encoder that we're doing a lossless transcode operation. If the
            // encoder is anything but a JPEG encoder, then this no longer is a lossless operation.
            // ( Details: Basically BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile
            //   tell the decoder to use the original image bits and BitmapCacheOption.None tells the decoder to wait
            //   with decoding. So, at the time of encoding the JPEG encoder understands that the input was a JPEG
            //   and just copies over the image bits without decompressing and recompressing them. Hence, this is a
            //   lossless operation. )
            BitmapDecoder original = BitmapDecoder.Create(originalFile, createOptions, BitmapCacheOption.None);
            if (!original.CodecInfo.FileExtensions.Contains("jpg"))
            {
                Console.WriteLine("The file you passed in is not a JPEG.");
                return;
            }
            JpegBitmapEncoder output = new JpegBitmapEncoder();
            // If you're just interested in doing a lossless transcode without adding metadata, just do this:
            //output.Frames = original.Frames;
            // If you want to add metadata to the image using the InPlaceBitmapMetadataWriter, first add padding:
            if (original.Frames[0] != null && original.Frames[0].Metadata != null)
            {
                // Your gut feel may want you to do something like:
                //     output.Frames = original.Frames;
                //     BitmapMetadata metadata = output.Frames[0].Metadata as BitmapMetadata;
                //     if (metadata != null)
                //     {
                //         metadata.SetQuery("/app1/ifd/PaddingSchema:Padding", paddingAmount);
                //     }
                // However, the BitmapMetadata object is frozen. So, you need to clone the BitmapMetadata and then
                // set the padding on it. Lastly, you need to create a "new" frame with the updated metadata.
                BitmapMetadata metadata = original.Frames[0].Metadata.Clone() as BitmapMetadata;
                // Of the metadata handlers that we ship in WIC, padding can only exist in IFD, EXIF, and XMP.
                // Third parties implementing their own metadata handler may wish to support IWICFastMetadataEncoder
                // and hence support padding as well.
                metadata.SetQuery("/app1/ifd/PaddingSchema:Padding", paddingAmount);
                metadata.SetQuery("/app1/ifd/exif/PaddingSchema:Padding", paddingAmount);
                metadata.SetQuery("/xmp/PaddingSchema:Padding", paddingAmount);
                // Since you're already adding metadata now, you can go ahead and add metadata up front.
                metadata.SetQuery("/app1/ifd/{uint=897}", "hello there");
                metadata.SetQuery("/app1/ifd/{uint=898}", "this is a test");
                metadata.Title = "This is a title";
                // Create a new frame identical to the one from the original image, except the metadata will have padding.
                // Essentially we want to keep this as close as possible to:
                //     output.Frames = original.Frames;
                output.Frames.Add(BitmapFrame.Create(original.Frames[0], original.Frames[0].Thumbnail, metadata, original.Frames[0].ColorContexts));
            }
            using (Stream outputFile = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite))
            {
                output.Save(outputFile);
            }
        }
        // For sanity, let's verify that the original and the output contain image bits that are the same.
        using (Stream originalFile = File.Open(originalPath, FileMode.Open, FileAccess.Read))
        {
            BitmapDecoder original = BitmapDecoder.Create(originalFile, createOptions, BitmapCacheOption.None);
            using (Stream savedFile = File.Open(outputPath, FileMode.Open, FileAccess.Read))
            {
                BitmapDecoder output = BitmapDecoder.Create(savedFile, createOptions, BitmapCacheOption.None);
                Compare(original.Frames[0], output.Frames[0], 0, "foo", Console.Out);
            }
        }
        // Let's copy the file before we use the InPlaceBitmapMetadataWriter so that you can verify the metadata changes.
        File.Copy(outputPath, finalPath, true);
        Console.WriteLine();
        // Now let's use the InPlaceBitmapMetadataWriter.
        using (Stream savedFile = File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite))
        {
            ConsoleColor  originalColor          = Console.ForegroundColor;
            BitmapDecoder output                 = BitmapDecoder.Create(savedFile, BitmapCreateOptions.None, BitmapCacheOption.Default);
            InPlaceBitmapMetadataWriter metadata = output.Frames[0].CreateInPlaceBitmapMetadataWriter();
            // Within the InPlaceBitmapMetadataWriter, you can add, update, or remove metadata.
            //metadata.SetQuery("/app1/ifd/{uint=899}", "this is a test of the InPlaceBitmapMetadataWriter");
            //metadata.RemoveQuery("/app1/ifd/{uint=898}");
            //metadata.SetQuery("/app1/ifd/{uint=897}", "Hello there!!");
            Console.WriteLine("#####################");
            Console.WriteLine(metadata.GetQuery(@"/app13/irb/8bimiptc/iptc/City"));
            Console.WriteLine("#####################");
            metadata.SetQuery(@"/app13/irb/8bimiptc/iptc/Headline", "TEst");
            metadata.SetQuery(@"/app13/irb/8bimiptc/iptc/City", "TEst");
            metadata.SetQuery(@"/app13/irb/8bimiptc/iptc/CountryPrimaryLocationName", "TEst");
            metadata.SetQuery(@"/app13/irb/8bimiptc/iptc/ByLine", "TEst");
            metadata.SetQuery(@"/app13/irb/8bimiptc/iptc/CaptionAbstract", "TEst");
            Console.WriteLine("#####################");
            Console.WriteLine(metadata.GetQuery(@"/app13/irb/8bimiptc/iptc/City"));
            Console.WriteLine("#####################");
            if (metadata.TrySave())
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("InPlaceMetadataWriter succeeded!");
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("InPlaceMetadataWriter failed!");
            }
            Console.ForegroundColor = originalColor;
        }
        FileInfo originalInfo = new FileInfo(originalPath);
        FileInfo outputInfo   = new FileInfo(outputPath);
        FileInfo finalInfo    = new FileInfo(finalPath);

        Console.WriteLine(outputPath);
        Console.WriteLine();
        Console.WriteLine("Original File Size: \t\t\t{0}", originalInfo.Length);
        Console.WriteLine("After Padding File Size: \t\t{0}", outputInfo.Length);
        Console.WriteLine("After InPlaceBitmapWriter File Size: \t{0}", finalInfo.Length);
    }