Добавьте цвет фона в MediaComposition

Я пытаюсь создать MediaComposition. Мне удалось объединить несколько изображений png в одно видео; однако созданные файлы имеют черный фон. Сначала я подумал, что это может быть из-за того, что файлы были png, но то же самое происходит и с jpg. Вот как я сохраняю изображение:

public async Task<bool> Save(InkCanvas canvas, StorageFile file)
{

    if (canvas != null && canvas.InkPresenter.StrokeContainer.GetStrokes().Count > 0)
    {
        if (file != null)
        {
            using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                await canvas.InkPresenter.StrokeContainer.SaveAsync(stream);
            }
        }
        Clear(canvas);
        return true;
    }
    return false;
}

Он отлично сохраняет изображение, но фон альфа. Это означает, что когда я пытаюсь связать их вместе в медиа-композицию, фона нет, и он отображается как черный. Я попытался использовать наложения при создании MediaComposition, чтобы исправить это:

MediaClip overlayVideoClip = MediaClip.CreateFromColor(Colors.White, new TimeSpan(0, 1, 0));
MediaOverlay mo = new MediaOverlay(overlayVideoClip);
MediaOverlayLayer mol = new MediaOverlayLayer();
mol.Overlays.Add(mo);

composition.OverlayLayers.Add(mol);

Но безрезультатно. Я подозреваю, что я неправильно понимаю значение термина наложение в этом случае. Итак, мои вопросы: возможно ли наложение видео во время композиции и, если да, то как? В качестве альтернативы, если это нужно сделать в самом изображении, как мне сохранить изображение с фоном?

РЕДАКТИРОВАТЬ:

Я добился прогресса (?) в этом; следующее компилируется и запускается, но создает сплошное черное изображение:

    public async Task TestSave(InkCanvas canvas, StorageFile file)
    {
        RenderTargetBitmap rtb = 
           new RenderTargetBitmap();
        PixelFormats.Pbgra32);
        await rtb.RenderAsync(canvas);
        var pixelBuffer = await rtb.GetPixelsAsync();

        using (IRandomAccessStream stream = 
             await file.OpenAsync(FileAccessMode.ReadWrite))
        {                
            BitmapEncoder encoder = 
                 await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);

            encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Straight,
                (uint)rtb.PixelWidth,
                (uint)rtb.PixelHeight,
                96d, 96d,
                pixelBuffer.ToArray());

            await encoder.FlushAsync();                
        }
    }

РЕДАКТИРОВАТЬ:

Я нашел этот ответ , что как бы решает проблему с помощью библиотеки Win2D; хотя это не решает мою настоящую проблему, это позволяет мне обойти ее. Надеюсь, есть лучшее решение.


person Paul Michaels    schedule 23.11.2015    source источник
comment
Непонятно, что вы пытаетесь сделать. Просто сохранить изображение без альфа-фона?   -  person Seth Kitchen    schedule 01.12.2015
comment
Либо сохраните изображение с фоном, либо наложите фон во время создания видеофайла (в настоящее время используется MediaComposition).   -  person Paul Michaels    schedule 01.12.2015


Ответы (1)


Единственное, что я понимаю, это то, что вы пытаетесь сохранить изображение с фоном. Мое предложение решить эту проблему - сохранить прозрачное изображение, которое у вас есть, что-то вроде

<StackPanel x:Name="AreaWhichWillBeSavedToImage" Background=*Some Color*>
  <Image x:Name="theAlphaImage">
</StackPanel>

Теперь, если вы не хотите, чтобы изображение отображалось в вашем графическом интерфейсе, просто установите для него значение «Скрытый».

Затем вы можете сохранить файл с цветом фона по вашему выбору.

var bitmap = await SaveToFileAsync(AreaWhichWillBeSavedToImage, await StorageFile.GetFileFromPathAsync(Windows.ApplicationModel.Package.Current.InstalledLocation.Path + @"someimage.jpg"));

  async Task<RenderTargetBitmap> SaveToFileAsync(FrameworkElement uielement, StorageFile file)
    {
        if (file != null)
        {
            CachedFileManager.DeferUpdates(file);

            Guid encoderId = GetBitmapEncoder(file.FileType);

            try
            {
                using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
                {
                    return await CaptureToStreamAsync(uielement, stream, encoderId);
                }
            }
            catch (Exception ex)
            {
                //DisplayMessage(ex.Message);
            }

            var status = await CachedFileManager.CompleteUpdatesAsync(file);
        }

        return null;
    }

    async Task<RenderTargetBitmap> CaptureToStreamAsync(FrameworkElement uielement, IRandomAccessStream stream, Guid encoderId)
    {
        try
        {
            var renderTargetBitmap = new RenderTargetBitmap();
            await renderTargetBitmap.RenderAsync(uielement);

            var pixels = await renderTargetBitmap.GetPixelsAsync();

            var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
            var encoder = await BitmapEncoder.CreateAsync(encoderId, stream);
            encoder.SetPixelData(
                BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Ignore,
                (uint)renderTargetBitmap.PixelWidth,
                (uint)renderTargetBitmap.PixelHeight,
                logicalDpi,
                logicalDpi,
                pixels.ToArray());

            await encoder.FlushAsync();

            return renderTargetBitmap;
        }
        catch (Exception ex)
        {
            //DisplayMessage(ex.Message);
        }

        return null;
    }

    Guid GetBitmapEncoder(string fileType)
    {
        Guid encoderId = BitmapEncoder.JpegEncoderId;
        switch (fileType)
        {
            case ".bmp":
                encoderId = BitmapEncoder.BmpEncoderId;
                break;
            case ".gif":
                encoderId = BitmapEncoder.GifEncoderId;
                break;
            case ".png":
                encoderId = BitmapEncoder.PngEncoderId;
                break;
            case ".tif":
                encoderId = BitmapEncoder.TiffEncoderId;
                break;
        }

        return encoderId;
    }
person Seth Kitchen    schedule 01.12.2015
comment
Сохраните изображение InkCanvas в качестве источника изображения AlphaImage, после чего оно заработает. - person Seth Kitchen; 04.12.2015
comment
Если вы имеете в виду следующее: ‹Image x:Name=theAlphaImage Source={Binding ElementName=myInkCanvas}›, то, похоже, это не работает. - person Paul Michaels; 04.12.2015
comment
Вы сохраняете свой inkCanvas в IRandomAccessStream. Этот поток легко преобразуется в Render Bitmap или WritableBitmap и т. д. После того, как вы преобразуете его в тип растрового изображения, вы можете установить источник изображения в растровое изображение. - person Seth Kitchen; 04.12.2015
comment
Хотя это работает (большое спасибо), изображение сохраняется только тогда, когда оно отображается в визуальном дереве. В противном случае он просто сохраняется как пустой. - person Paul Michaels; 16.12.2015