2012-02-13 14 views
8

Próbuję zrozumieć, dlaczego moje obrazy nie są zgryźliwe, więc zbudowałem próbkę do testowania wydajności WPF. Użyłem zegara, aby obliczyć, jak długo wykonywana jest moja funkcja "wyświetlania obrazów", i wykorzystałem stoper do mierzenia czasu, w jakim obrazy pojawiły się na ekranie. W dolnej linii: podczas wyświetlania obrazów 100, 1600, 2500 i 3600, WPF zajęło 2, 9, 12 i 16 sekund po mój kod został zakończony, aby wyświetlić obrazy na ekranie. Więc czuję się bezradny: Wydaje się, że nie mogę poprawić kodu, aby obrazy wyglądały szybciej - muszę coś zrobić z WPF!WPF Bitmap wydajność

Moje pytanie brzmi: Co muszę zrobić inaczej, aby obrazy wyświetlały się szybciej?


Konfiguracja Test jest prosty:

Okno zawiera siatki. Po naciśnięciu przycisku „test” kliknięciu wiersz i kolumna definicje są added.Then obraz jest dodawany do każdej komórki siatki następująco:

  var image = new Image(); 
      image.BeginInit(); 
      image.Name = ImageNameFromCell(theRow, theColumn); 
      image.Stretch = Stretch.None; 
      image.HorizontalAlignment = HorizontalAlignment.Center; 
      image.VerticalAlignment = VerticalAlignment.Center; 
      RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.LowQuality); 
      image.EndInit(); 

      theGrid.Children.Add(image); 

Wreszcie Źródło każdego obrazu jest ustawiony na bitmapę: obraz w skali szarości jest już zmniejszony do szacowanego rozmiaru ekranu. Bitmapa jest generowana w następujący sposób:

  var smallerBitmapImage = new BitmapImage(); 
      smallerBitmapImage.BeginInit(); 
      smallerBitmapImage.DecodePixelWidth = (int)(theImageWidth); 
      smallerBitmapImage.UriSource = theUri; 
      smallerBitmapImage.CacheOption = BitmapCacheOption.None; 
      smallerBitmapImage.EndInit(); 

      //BitmapFrame bitmapFrame = BitmapFrame.Create(this.FullPath); 

      var convertedBitmap = new FormatConvertedBitmap(); 
      convertedBitmap.BeginInit(); 
      convertedBitmap.Source = smallerBitmapImage; 
      convertedBitmap.DestinationFormat = PixelFormats.Gray16; 
      convertedBitmap.EndInit(); 
      convertedBitmap.Freeze(); 

Tak, jestem na końcu rozumu. Obrazy pojawiają się z zauważalnym opóźnieniem i wydaje się, że jest poza moją kontrolą. Co mogę zrobić?

Odpowiedz

3

Co wydaje się dokonały różnica jest ustawienie opcji obrazka cache do onload

smallerBitmapImage.CacheOption = BitmapCacheOption.OnLoad;

Przeniosło to pracę na moją obsługę zdarzeń, więc teraz mogę użyć pobierania wstępnego, aby zrobić to w tle.

3

Czy faktycznie widzisz wszystkie te obrazy w tym samym czasie? Jeśli nie, możesz użyć części ItemsControl z panelem wirtualizacji, aby wyświetlić tylko obrazy w widoku. (Mówiąc o panelach, aktualna konfiguracja może również zostać zastąpiony ItemsControl który wykorzystuje UniformGrid jak panel)

Można także spróbować napisać lepszy dekoder, który prawdopodobnie jest zmarnowany wysiłek.

+0

Dziękuję za odpowiedź, H.B. Tak, chcę zobaczyć wszystkie te obrazy w tym samym czasie. 1600, 2500 i 3600 przypadków było do testowania, więc mogłem łatwo zmierzyć opóźnienie WPF z sekundowym zegarkiem zegarka, ale powiedziałbym, że 400 obrazów to liczba, którą chciałbym wesprzeć. I ponownie sugestia "lepszego dekodera", myślałem, że dekodowanie było już wykonane w powyższym kodzie "lowerBitmapImage", tj. W moim kodzie, a nie w czasie, w którym WPF robi to, co robi po powrocie funkcji obsługi zdarzeń, co jest czasem Próbuję skrócić ... – Avi

+1

@Avi: Och tak, ponieważ pliki prawdopodobnie są lokalne, dekodowanie może się zdarzyć synchronicznie, ale nie jestem pewien co do wewnętrznych elementów; biorąc pod uwagę, że konwersja nie generuje wyjątków, jednak założenie wydaje się wykonalne. Jeśli sprowadza się to do czystego czasu renderowania, to naprawdę możesz być w wiązaniu, ponieważ wydajesz się robić wszystko, co przyspiesza proces od dekodowania do mniejszego rozmiaru, aby zapobiec skalowaniu. Nie wiem, co jeszcze można tu zrobić :( –