我試圖在Adobe Premiere中像這樣創建時間比例尺: 但是,我必須下降到0.01秒的增量。當圖像超過40,000寬時,渲染圖像失敗
我的時間軸控制的樣子:
UPDATE: 我用@Sten彼得羅夫的建議,並使用了VisualBrush
。
但現在我被困在如何實現秒爲Label
。
我的新代碼(含控制可以改變):
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="680.839">
<Grid Background="Black">
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible" >
<ScrollViewer.ContentTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid SnapsToDevicePixels="False" UseLayoutRounding="True">
<Grid.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,5,30" ViewportUnits="Absolute" Viewbox="0,0,5,30" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Line Stroke="Coral" StrokeThickness="2" X1="0" X2="0" Y1="25" Y2="30" UseLayoutRounding="True" />
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
</Grid>
<Grid Margin="50,0,0,0" SnapsToDevicePixels="False" UseLayoutRounding="True">
<Grid.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,50,30" ViewportUnits="Absolute" Viewbox="0,0,50,30" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Line Stroke="Red" StrokeThickness="2" X1="0" X2="0" Y1="20" Y2="30" UseLayoutRounding="True" />
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
</Grid>
<Grid SnapsToDevicePixels="False" Height="30" UseLayoutRounding="True" >
<Grid.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,500,30" ViewportUnits="Absolute" Viewbox="0,0,500,30" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Grid HorizontalAlignment="Left" Width="500" UseLayoutRounding="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="21*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="9*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="1" Height="9" Content=".100" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="2" Height="9" Content=".200" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="3" Height="9" Content=".300" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="4" Height="9" Content=".400" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="5" Height="9" Content=".500" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="6" Height="9" Content=".600" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="7" Height="9" Content=".700" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="8" Height="9" Content=".800" Foreground="White"/>
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="9" Height="9" Content=".900" Foreground="White"/>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
</Grid>
<Grid SnapsToDevicePixels="False" Height="30" UseLayoutRounding="True" Margin="500,0,0,0" >
<Grid.Background>
<VisualBrush TileMode="Tile" Viewport="0,0,500,30" ViewportUnits="Absolute" Viewbox="0,0,500,30" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Line Stroke="Blue" StrokeThickness="2" X1="0" X2="0" Y1="10" Y2="30" UseLayoutRounding="True" />
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
</Grid>
<Grid SnapsToDevicePixels="False" Height="30" UseLayoutRounding="True" Margin="491,0,0,0" >
<Grid.RowDefinitions>
<RowDefinition Height="7"/>
<RowDefinition Height="23"/>
</Grid.RowDefinitions>
<!--Need something here-->
<Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="0" Height="9" Content="00:00" Foreground="White"/>
</Grid>
</Grid>
</DataTemplate>
</ScrollViewer.ContentTemplate>
</ScrollViewer>
</Grid>
/UPDATE
我去每行0.01秒,所以10分鐘的時間線我期待繪製60000行+ 6000個標籤。在Canvas
10000's+ UI elements, bind or draw?
本來我是畫線直接:
我問了一個問題,之前在這之前。 然後我去使用VisualHost
,因爲它應該是較輕的重量。
那麼它不夠輕。
我有一個MediaElement
播放視頻和時間軸滾動與視頻位置同步。 A ScrollViewer
包裝我的時間軸,並且每10ms做.ScrollToHorizontalOffset
。
如果我的時間軸結束了3分鐘的視頻快門。 我認爲這是因爲VisualHost
仍然具有所有框架元素,並且滾動導致它們被重新驗證。
所以現在我試圖產生一個Image
顯示,我認爲應該更輕。
我在這個假設中錯了嗎?
現在我正面臨着將時間線變成Image
的問題。
我無法將整個時間線渲染成圖像,所以我'拼湊'它。我正在打Exceptions
關於圖像大小。
對我的代碼: 這是我的主要切入點。
public void RenderHeaderPicture()
{
const int ChunkSize = 5000;
var bitmapFrames = new List<BitmapFrame>();
// generates X number of DrawingVisual's based on ChunkSize
List<DrawingVisual> visuals = generateHeaderVisualChunks(
AppViewModel.TimelineViewModel.HeaderWidth, ChunkSize, TimelineViewModel.ViewLevel.Level1);
for (var i = 0; i < visuals.Count; i++)
{
var renderTargetBitmap = new RenderTargetBitmap(ChunkSize, 30, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(visuals[i]);
//test to make sure image good
saveHeaderSegmentAsPng(string.Format("headerSeg{0}.png", i), renderTargetBitmap);
bitmapFrames.Add(BitmapFrame.Create(renderTargetBitmap));
}
// put the frames back together now
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
for (int i = 0; i < bitmapFrames.Count; i++)
{
drawingContext.DrawImage(bitmapFrames[i], new Rect(i * ChunkSize, 0, bitmapFrames[i].PixelWidth, 30));
}
drawingContext.Close();
}
var newBmp = new RenderTargetBitmap(AppViewModel.TimelineViewModel.HeaderWidth, 30, 96, 96, PixelFormats.Pbgra32);
newBmp.Render(drawingVisual);
AppViewModel.TimelineViewModel.HeaderImageSource = newBmp;
}
這裏是創建DrawingVisual's
private List<DrawingVisual> generateHeaderVisualChunks(int width, int chunkSize, TimelineViewModel.ViewLevel level)
{
var ret = new List<DrawingVisual>();
var currentTime = new TimeSpan(0, 0, 0, 0, 0);
var timeStep = new TimeSpan(0, 0, 0, 0, (int)level);
var currentLine = 0;
const double DistanceBetweenLines = 5;
const int TenthOfSecondLine = 10;
const int SecondLine = 100;
int iterations = (width/chunkSize);
int remainder = width % chunkSize; //not doing anything with yet
var grayBrush = new SolidColorBrush(Color.FromRgb(192, 192, 192));
var grayPen = new Pen(grayBrush, 2);
var whitePen = new Pen(Brushes.Purple, 2);
grayBrush.Freeze();
grayPen.Freeze();
whitePen.Freeze();
for (int i = 0; i < iterations; i++)
{
var visual = new DrawingVisual();
using (var dc = visual.RenderOpen())
{
double currentX = 0;
if (i > 0)
{
currentLine--;
currentTime -= timeStep;
}
while (currentX <= chunkSize)
{
if (((currentLine % SecondLine) == 0) && currentLine != 0)
{
dc.DrawLine(whitePen, new Point(currentX, 30), new Point(currentX, 15));
FormattedText text = null;
double tempX = currentX;
switch (level)
{
case TimelineViewModel.ViewLevel.Level1:
text = new FormattedText(
currentTime.ToString(@"hh\:mm\:ss\.fff"),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Tahoma"),
8,
grayBrush);
break;
}
dc.DrawText(text, new Point((tempX - 22), 0));
}
else if ((((currentLine % TenthOfSecondLine) == 0) && currentLine != 0)
&& (currentLine % SecondLine) != 0)
{
dc.DrawLine(grayPen, new Point(currentX, 30), new Point(currentX, 20));
FormattedText text = null;
switch (level)
{
case TimelineViewModel.ViewLevel.Level1:
text = new FormattedText(
string.Format(".{0}", currentTime.Milliseconds),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Tahoma"),
8,
grayBrush);
break;
}
dc.DrawText(text, new Point((currentX - 8), 8));
}
else
{
dc.DrawLine(grayPen, new Point(currentX, 30), new Point(currentX, 25));
}
currentX += DistanceBetweenLines;
currentLine++;
currentTime += timeStep;
}
}
ret.Add(visual);
}
return ret;
}
保存PNG段代碼:
private static void saveHeaderSegmentAsPng(string fileName, RenderTargetBitmap renderTargetBitmap)
{
var pngBitmapEncoder = new PngBitmapEncoder();
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (var fileStream = new FileStream(fileName, FileMode.Create))
{
pngBitmapEncoder.Save(fileStream);
fileStream.Flush();
fileStream.Close();
}
}
我所有的PNG段在其單獨的文件中正確呈現。 我的時間軸被正確渲染,直到我超過1:20然後事情中斷。
請參見:
這就像圖像被弄髒或東西。 任何人都知道這是怎麼回事?
感謝
「我在這個假設中錯了嗎?」是。 「它不夠輕。」爲什麼它不夠輕?也許你應該考慮虛擬化,只繪製可見的東西而不是一切。不知道你以前是怎麼做的,我們無法修復它。但圖像的東西絕對不是輕量級的。 – 2013-03-20 21:05:10
我以前使用過'VisualHost',generateHeaderVisualChunks就是我會用的,但沒有分塊。 它不夠輕,因爲'VisualHost'會導致我的視頻跳過。我的ScrollViewer將當前視頻位置保持在ScrollViewer的中心位置,因此ScrollViewer每滾動約10ms。 – jpiccolo 2013-03-20 22:07:07
我在generateHeaderVisualChunks中注意到的一件事是,你的筆,畫筆和字體應該在函數之外創建,也許是靜態的,不需要通過創建新的對GC施加壓力,它們不會改變。我還想知道是否可以在視覺中生成比視覺更大的內容,允許scrollviewer移動它,檢測何時接近結束,然後再生成。換句話說,把它分解成更大的塊,這樣你就不會像往常那樣做繁重的工作。 – 2013-03-20 22:54:24