protected override void InitWidgetFromToken(SaveConfigToken token)
        {
            HDPhotoSaveConfigToken hdToken = (HDPhotoSaveConfigToken)token;

            this.qualitySlider.Value = hdToken.Quality;
            this.bpp24RB.Checked     = (hdToken.BitDepth == 24);
            this.bpp32RB.Checked     = (hdToken.BitDepth == 32);
        }
        private void OnSaveImpl(
            Document input,
            Stream output,
            SaveConfigToken token,
            Surface scratchSurface,
            ProgressEventHandler callback)
        {
            HDPhotoSaveConfigToken hdToken = token as HDPhotoSaveConfigToken;
            WmpBitmapEncoder       wbe     = new WmpBitmapEncoder();

            using (RenderArgs ra = new RenderArgs(scratchSurface))
            {
                input.Render(ra, true);
            }

            MemoryBlock block = scratchSurface.Scan0;
            IntPtr      scan0 = block.Pointer;

            double dpiX;
            double dpiY;

            switch (input.DpuUnit)
            {
            case MeasurementUnit.Centimeter:
                dpiX = Document.DotsPerCmToDotsPerInch(input.DpuX);
                dpiY = Document.DotsPerCmToDotsPerInch(input.DpuY);
                break;

            case MeasurementUnit.Inch:
                dpiX = input.DpuX;
                dpiY = input.DpuY;
                break;

            case MeasurementUnit.Pixel:
                dpiX = Document.GetDefaultDpu(MeasurementUnit.Inch);
                dpiY = Document.GetDefaultDpu(MeasurementUnit.Inch);
                break;

            default:
                throw new InvalidEnumArgumentException();
            }

            BitmapSource bitmapSource = BitmapFrame.Create(
                scratchSurface.Width,
                scratchSurface.Height,
                dpiX,
                dpiY,
                System.Windows.Media.PixelFormats.Bgra32,
                null,
                scan0,
                (int)block.Length, // TODO: does not support >2GB images
                scratchSurface.Stride);

            FormatConvertedBitmap fcBitmap = new FormatConvertedBitmap(
                bitmapSource,
                hdToken.BitDepth == 24 ? PixelFormats.Bgr24 : PixelFormats.Bgra32,
                null,
                0);

            BitmapFrame outputFrame0 = BitmapFrame.Create(fcBitmap);

            wbe.Frames.Add(outputFrame0);
            wbe.ImageQualityLevel = (float)hdToken.Quality / 100.0f;

            string tempFileName = FileSystem.GetTempFileName();

            FileStream tempFileOut = new FileStream(tempFileName, FileMode.Create, FileAccess.Write, FileShare.Read);

            wbe.Save(tempFileOut);
            tempFileOut.Close();
            tempFileOut = null;

            FileStream                  tempFileIn = new FileStream(tempFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
            WmpBitmapDecoder            wbd        = new WmpBitmapDecoder(tempFileIn, BitmapCreateOptions.None, BitmapCacheOption.None);
            BitmapFrame                 ioFrame0   = wbd.Frames[0];
            InPlaceBitmapMetadataWriter metadata2  = ioFrame0.CreateInPlaceBitmapMetadataWriter();

            CopyMetadataTo(metadata2, input.Metadata);
            tempFileIn.Close();
            tempFileIn = null;

            FileStream tempFileIn2 = new FileStream(tempFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);

            Utility.CopyStream(tempFileIn2, output);
            tempFileIn2.Close();
            tempFileIn2 = null;

            try
            {
                File.Delete(tempFileName);
            }

            catch (Exception)
            {
            }

            // WPF doesn't give us an IDisposable implementation on its types
            Utility.GCFullCollect();
        }