向 MediaComposition 添加背景颜色
Add a background colour to a 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;
}
保存图像很好,但背景是 alpha。这意味着当我尝试将它们链接到媒体组合中时,没有背景,并且呈现为黑色。我在创建 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 库解决了问题;虽然它没有解决我的实际问题,但它让我放过它。希望有更好的解决方案。
我对此的唯一了解是您正在尝试保存带有背景的图像。我解决这个问题的建议是将透明图像保存为
之类的东西
<StackPanel x:Name="AreaWhichWillBeSavedToImage" Background=*Some Color*>
<Image x:Name="theAlphaImage">
</StackPanel>
现在,如果您不想在 GUI 上显示图像,只需将其设置为隐藏即可。
然后您可以使用您选择的颜色背景保存文件。
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;
}
我正在尝试创建一个 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;
}
保存图像很好,但背景是 alpha。这意味着当我尝试将它们链接到媒体组合中时,没有背景,并且呈现为黑色。我在创建 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();
}
}
编辑:
我找到了
我对此的唯一了解是您正在尝试保存带有背景的图像。我解决这个问题的建议是将透明图像保存为
之类的东西<StackPanel x:Name="AreaWhichWillBeSavedToImage" Background=*Some Color*>
<Image x:Name="theAlphaImage">
</StackPanel>
现在,如果您不想在 GUI 上显示图像,只需将其设置为隐藏即可。
然后您可以使用您选择的颜色背景保存文件。
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;
}