Vorschau beschleunigen



  • Hi zusammen!

    Ich habe ein Programm geschrieben, welches Bilder (gif, jpg und bmp) aus einem bestimmten Verzeichnis auflistet (TListView).
    Zudem wird auch noch eine Vorschau angezeigt, wenn man einen Eintrag aus der Liste ausfüllt. Dabei wird das Bild über
    TJPEGImage, TGIFImage oder TPicture auf ein TImage geschoben. TImage hat maximal die Breite von 169px oder halt die Höhe.
    Das Problem ist das immer das ganze Bild eigentlich in voller Größe geladen wird und dann nur auf dem TImage verkleinert
    wird. Daher ist es dann bei Bilder um die 1MB (Fotos in JPG) problematisch wenn man über die Cursor sich in der TListView hoch und runter
    bewegt. Da das Laden immer einige Zeit in anspruch nimmt.

    Kann man die Vorschau vielleicht noch ein wenig schneller Laden? Wenn ich die OpenPictureDialog Vorschau sehe, dann geht
    das auch bedeutend schneller. Sowie die Miniaturansicht von WindowsXP. Diese wirkt auch bedeutend schärfer.

    In der Suche und den FAQs habe ich leider nix passendes gefunden und hoffe das ich auf Eure Hilfe zählen kann.

    Thanx
    Heinzelmännchen



  • Vielleicht hilfts ja die Eigenschaft PixelFormat niedriger zu stellen.



  • Hi,

    das würde mir derzeit nicht sonderlich helfen.

    Wie wird es denn bei der Miniaturvorschau (WinXP) im Allgemeinen gemacht? Werden die dort irgendwie anders geladen?



  • 'Das Problem ist das immer das ganze Bild eigentlich in voller Größe geladen wird und dann nur auf dem TImage verkleinert '

    Was meinst Du damit genau?

    Ich lade die Bilder in ein TPictur und 'schreibe' die mit StretchDraw() in das TImage - das geht relativ schnell. In TImage ist dann nur ein 'Thumbnail' mit weniger Pixeln, das wird schnell angezeigt!

    Oder lade alle Bilder des Ordners in einem Thread 'voraus' in kleine TBitmaps. Bei Auswahl eines Eintrages kann mit Draw das Bild schnell in TImage angezeigt werden.



  • Hi,

    also meine derzeitig Ausgangslage ist:

    Ich habe eine Liste die einen selektierten Ordner wiederspiegelt und wenn ich ein Bild aus der Liste auswähle dann soll eine Vorschau erscheien. Dabei soll die Vorschau auf 169px skaliert werden. Die Bilder sind meist in einer Auflösung von 1600x1200 Pixeln und um den MB groß.

    Hier ein Code Auszug:

    TJPEGImage *_JPGPicture = new TJPEGImage();
    _JPGPicture->LoadFromFile(strFilename);
    
    if (_JPGPicture->Width > _JPGPicture->Height) {
      PreviewImg->Height = 169 / ((float) _JPGPicture->Width / (float) _JPGPicture->Height);
      PreviewImg->Width = 169;
      PreviewImg->Top = 8 + (169 - PreviewImg->Height) / 2;
      PreviewImg->Left = 8;
    }
    else {
      PreviewImg->Height = 169;
      PreviewImg->Top = 8;
      PreviewImg->Width = 169 / ((float) _JPGPicture->Height / (float) _JPGPicture->Width);
      PreviewImg->Left = 8 + (169 - PreviewImg->Width) / 2;
    }
    PreviewImg->Picture->Assign(_JPGPicture);
    
    delete _JPGPicture;
    

    Über eine Optimierte Lösung wäre ich sehr froh.



  • Mach mal folgende Ersetzung:

    //PreviewImg->Picture->Assign(_JPGPicture);
    PreviewImg->Canvas->StretchDraw(Rect(0,0,PreviewImg->Width,PreviewImg->Height),_JPGPicture);



  • Dass mit ziemlicher Sicherheit die Stretch-Property des PreviewImg bereits aktiviert ist, daran hast du gedacht?
    Scheinbar nicht, denn TCanvas::StretchDraw ist ungefähr 300mal langsamer. 😉



  • Ok!

    PreviewImg->Stretch sollte natuerlich false gesetzt werden!

    Bei mir geht das schneller! (???) Das Anzeigen 'gestretchter' Images ist nur so langsam: je nach zoom- Faktor!

    Eventuell hilft die WinApi noch weiter.



  • DerAltenburger schrieb:

    PreviewImg->Stretch sollte natuerlich false gesetzt werden!

    Nein. Stretch sollte auf true gestellt werden/bleiben und dafür auf deinen StretchDraw-Vorschlag verzichtet werden. 😉
    Meine "Teststrecke":

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      Screen->Cursor = crHourGlass;
    
      TJPEGImage *jpg = new TJPEGImage();
      jpg->LoadFromFile("c:\\001.jpg");
    
      Image1->Width = 160;
      Image1->Height = 120;
      Image1->Picture = NULL;
      Application->ProcessMessages();
    
      int x = 10000;
      LARGE_INTEGER start, end;
      QueryPerformanceCounter(&start);
    
      if (CheckBox1->Checked)
      {
        Image1->Stretch = true;
        for (int i = 0; i < x; i++)
          Image1->Picture->Assign(jpg);
      }
      else
      {
        Image1->Stretch = false;
        TRect rect = Rect(0,0,Image1->Width,Image1->Height);
        for (int i = 0; i < x; i++)
          Image1->Canvas->StretchDraw(rect ,jpg);
      }
    
      QueryPerformanceCounter(&end);
      int result = (end.QuadPart - start.QuadPart) / x;
      if (CheckBox1->Checked)
        Label1->Caption = "Assign()   : " + String(result);
      else
        Label1->Caption = "StretchDraw: " + String(result);
    
      delete jpg;
      Screen->Cursor = crDefault;
    
    }
    

    Ich komme bein einem 1600x1200/900KB JPEG auf Ergebnisse von 20 zu 13.000 zugunsten von Assign, das ist sogar 650mal schneller.



  • Hallo zusammen!

    Erstmal großen Dank an Euch, dass ihr euch den Kopf mitzerbrecht.

    Das mit den Canvas habe ich gleich aussprobiert und getestet. Leider ist das so wie Jansen es schon angedeutet hattet. Es ist echt meiner Empfindung nach noch langsamer.

    Hier wurde aber noch WinAPI angesprochen. Wird es dadurch bedeutend schneller oder wäre es nur eine Alternative?



  • naja, Using GDI+ bitmaps and images hilft vielleicht weiter. GDI+ sollte scheller sein.


Anmelden zum Antworten