2013-03-20 67 views
2

我試圖在Adobe Premiere中像這樣創建時間比例尺: enter image description here 但是,我必須下降到0.01秒的增量。當圖像超過40,000寬時,渲染圖像失敗

我的時間軸控制的樣子: enter image description here

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個標籤。在Canvas10000'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然後事情中斷。

請參見: enter image description here

這就像圖像被弄髒或東西。 任何人都知道這是怎麼回事?

感謝

+0

「我在這個假設中錯了嗎?」是。 「它不夠輕。」爲什麼它不夠輕?也許你應該考慮虛擬化,只繪製可見的東西而不是一切。不知道你以前是怎麼做的,我們無法修復它。但圖像的東西絕對不是輕量級的。 – 2013-03-20 21:05:10

+0

我以前使用過'VisualHost',generateHeaderVisualChunks就是我會用的,但沒有分塊。 它不夠輕,因爲'VisualHost'會導致我的視​​頻跳過。我的ScrollViewer將當前視頻位置保持在ScrollViewer的中心位置,因此ScrollViewer每滾動約10ms。 – jpiccolo 2013-03-20 22:07:07

+0

我在generateHeaderVisualChunks中注意到的一件事是,你的筆,畫筆和字體應該在函數之外創建,也許是靜態的,不需要通過創建新的對GC施加壓力,它們不會改變。我還想知道是否可以在視覺中生成比視覺更大的內容,允許scrollviewer移動它,檢測何時接近結束,然後再生成。換句話說,把它分解成更大的塊,這樣你就不會像往常那樣做繁重的工作。 – 2013-03-20 22:54:24

回答

3

我在等待這一天,當我住的房間將與水平分辨率,這將需要一些你的方法一臺電視機。

將你剛纔演示的代碼全部廢棄,它永遠不會變得可用可維護,你只能設法擠出其中的一個。

然後瞭解VisualBrush,也有很多教程在那裏,它可以重複你的視覺模板,無需PNG格式的,它會更好的規模時屏幕分辨率更改(可達40001px寬)

對於數字那些出現在標記上方的數百種不同的方法,其中一些可以與上面提到的視覺刷相結合,例如代表時間軸單位的用戶控件(兩個較大標記之間的空間)。現在將它們中的一些放置在網格中(堆疊面板,畫布...如您所願)並調整(動態)它們的偏移和標籤 - 突然間,您可以用屏幕上的10個控件表示無限時間軸。