JPEGImage + ProgressBar

problemy z tworzeniem aplikacji graficznych oraz audio i wideo

JPEGImage + ProgressBar

Nowy postprzez mervinjmicky » Å›roda, 27 stycznia 2010, 18:39

Witam,
Chciałbym do mojej funkcji dodać postęp wczytywania pliku JPG. Nie używam TImage tylko
Kod: Zaznacz cały
TJPEGImage *jpg = new TJPEGImage();

i wczytuje pliczek za pomocÄ…:
Kod: Zaznacz cały
jpg->Assign(plik);

dodatkowo zapisuje tego jpg na dysk:
Kod: Zaznacz cały
   jpg->CompressionQuality = quality;
   jpg->SaveToFile(temp+"\\\\plik.jpg");

Gdy są to pliki 8mb i większe to chwile to trwa dlatego chciałbym umieścić ProgressBar'a na formatce i tam pokazywać status. Czy jest coś takiego możliwe?
Avatar użytkownika
mervinjmicky
Bladawiec
Bladawiec
 
Posty: 9
Dołączył(a): środa, 27 stycznia 2010, 18:36
PodziÄ™kowaÅ‚ : 3
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
System operacyjny: Kubuntu 9.10
Kompilator: C++ Builder 6
Gadu Gadu: 0
    LinuxChrome

Re: JPEGImage + ProgressBar

Nowy postprzez Witold » Å›roda, 27 stycznia 2010, 21:14

mervinjmicky napisał(a):Gdy są to pliki 8mb i większe to chwile to trwa dlatego chciałbym umieścić ProgressBar'a na formatce i tam pokazywać status. Czy jest coś takiego możliwe?


Obsługa zdarzenia TJPEGImage::OnProgress może okazać się pomocna, szczegóły w helpie.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 14
Kompilator: bcb6, Turbo C++ Explorer
    Windows XPOpera

Re: JPEGImage + ProgressBar

Nowy postprzez Cyfrowy Baron » Å›roda, 27 stycznia 2010, 21:52

Teoretycznie to powinno wyglądać tak:

Kod: Zaznacz cały
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
  Image = new TJPEGImage();
  Image->OnProgress = ImageProgress;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageProgress(TObject *Sender, TProgressStage Stage,
     BYTE PercentDone, bool RedrawNow, const TRect &R, const AnsiString Msg)
{
   ProgressBar1->Position = PercentDone;

   if(!RedrawNow) ProgressBar1->Position = 0;
}
//---------------------------------------------------------------------------


Ale klasa TJPEGImage jak i TBitmap nie maja wsparcia dla tego zdarzenie, a więcej na ten temat przeczytasz tutaj: https://forums.embarcadero.com/thread.j ... eadID=7637

Zdarzenie OnProgress działa tylko z kontrolkami graficznymi, czyli z TImage.



Tutaj: http://www.delphisources.ru/pages/faq/b ... iewer.html jest chyba podany kod w Delphi jak to można zrobić inaczej, ale nie sprawdzałem, tylko rzuciłem na niego okiem.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: JPEGImage + ProgressBar

Nowy postprzez Witold » Å›roda, 27 stycznia 2010, 23:52

Cyfrowy Baron napisał(a):Ale klasa TJPEGImage jak i TBitmap nie maja wsparcia dla tego zdarzenie, a więcej na ten temat przeczytasz tutaj: https://forums.embarcadero.com/thread.j ... eadID=7637

Zdarzenie OnProgress działa tylko z kontrolkami graficznymi, czyli z TImage.


Chyba nie uważnie przeczytałeś to co podałeś. TJPEGImage wywołuje TProgressEvent.

Remy Lebeau napisał(a):... The TJPEGImage class does
implement the OnProgress event, because a JPG image involves
compression/decompression and interlacing, so TJPEGImage implements the
OnPress event so the image can be rendered visually at various stages.


Użycie RedrawNow też Ci chyba nie wyszło:
Cyfrowy Baron napisał(a):
Kod: Zaznacz cały
if(!RedrawNow) ProgressBar1->Position = 0;



help napisał(a):The RedrawNow parameter indicates whether the image can safely be drawn on screen at this point. The R parameter specifies the portion of the image that has changed and needs to be redrawn.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 14
Kompilator: bcb6, Turbo C++ Explorer
    Windows XPOpera

Re: JPEGImage + ProgressBar

Nowy postprzez Cyfrowy Baron » czwartek, 28 stycznia 2010, 10:20

Wszystko działa prawidłowo w zdarzeniu OnProgress obiektu Image, w TJPEGImage nie działa wogóle. Co do RedrawNow to wyszło, gdy obraz jest odrysowywany ta zmienna posiada wartość true, gdy zakończy się jego odrysowywanie to przyjmuje wartość false. Jeżeli grafika nie może być odrysowana, to RedrawNow posiada wartość false, więc może być użyty do sterowania ProgressBar. Z RedrawNow czy bez niego sterowanie ProgressBar w zdarzeniu OnProgress obiektu TJPEGImage nie działa.

Zamiast RedrawNow można oczywiście użyć argumentu Stage:

Kod: Zaznacz cały
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageProgress(TObject *Sender, TProgressStage Stage,
     BYTE PercentDone, bool RedrawNow, const TRect &R, const AnsiString Msg)
{
  switch(Stage)
  {
   case psStarting: ProgressBar1->Position = 0; break;
   case psRunning:  ProgressBar1->Position = PercentDone; break;
   case psEnding:   ProgressBar1->Position = 100; break;
  }
}
//---------------------------------------------------------------------------


Chyba nie uważnie przeczytałeś to co podałeś. TJPEGImage wywołuje TProgressEvent.


Nie wywołuje.

Remy Lebeau ma rację tylko, że Ty nie bierzesz pod uwagę kontekstu wypowiedzi, a tyczy się ona odnośnie pliku JPG ładowanego do obiektu Image poprzez Picture, dlatego cytowane przez ciebie wypowiedź jest poprzedzona:
You are telling TPicture to load a JPG image.


a całość wypowiedzi tyczy się tego kodu:

Kod: Zaznacz cały
        procedure TForm1.Button1Click(Sender: TObject);
        // this is TImage StretchDraw (Part 1)
        var
        Image1: TImage;
        begin
        Image1 := TImage.Create(self);
        Image1.Parent := ScrollBox1;
        Image1.AutoSize := true;
        Image1.OnProgress := ProgressUpdate;
        Image1.Picture.LoadFromFile('TestImg.jpg'); // event works
        // Image1.Picture.LoadFromFile('Covpgh.bmp'); // will load, but no event
        // end of Part 1



Zauważ, że OnProgress został podłączony pod obiekt typu TImage a nie TJPEGImage, a w przypadku TImage działa bez zarzutu, ale tylko dla pliku w formacje JPEG, gdyż pliki JPEG mogą być wczytywane progresywnie a bitmapy nie dlatego nie działa w odniesieniu do pliku w formacie BMP. Po części wiec masz rację, że klasa TJPEGImage wywołuje zdarzenie OnProgress, ale nie jest to zdarzenie tej klasy, lecz zdarzenie odziedziczone po klasie TGraphics i działa tylko w połączeniu z obiektem TImage.

It is not supposed to. Most TGraphic-derived classes, including TBitmap, donot implement the OnProgress event to begin with, as they usually don't need it.


Tego fragmentu chyba też nie przeczytałeś. TJPEGImage dziedziczy po TGraphics i jak sądzę ta wypowiedź też się tyczy tego typu.

W plikach pomocy do BCB nie ma nic na temat klasy TJPEGImage.



Jeszcze coś co mi umknęło wcześniej:

i wczytuje pliczek za pomocÄ…:

Kod: Zaznacz cały
            jpg->Assign(plik);


Do wczytywania plików do obiektu klasy TJPEGImage służy funkcje LoadFromFile, a nie Assign. Funkcja Assign tylko kopiuje jeden obiekt do drugiego.



Kolejna sprawa, to zdarzenie OnProgress obiektu typu TImage działa tylko w odniesieniu do wczytywania obrazka, nie jest wogóle wywoływane przy zapisywaniu zawartości TImage.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
mervinjmicky
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: JPEGImage + ProgressBar

Nowy postprzez Witold » czwartek, 28 stycznia 2010, 12:09

Cyfrowy Baron napisał(a):Wszystko działa prawidłowo w zdarzeniu OnProgress obiektu Image w TJPEGImage nie działa wogóle.


Działa dla kompresji/dekompresji (sprawdziłem).

Cyfrowy Baron napisał(a):Co do RedrawNow to wyszło, gdy obraz jest odrysowywany ta zmienna posiada wartość true, gdy zakończy się jego odrysowywanie to przyjmuje wartość false. Jeżeli grafika nie może być odrysowana, to RedrawNow posiada wartość false, więc może być użyty do sterowania ProgressBar. Z RedrawNow czy bez niego sterowanie ProgressBar w zdarzeniu OnProgress obiektu TJPEGImage nie działa.


Chyba musisz przeczytać opis z helpa jeszcze raz.

Cyfrowy Baron napisał(a):Zauważ, że OnProgress został podłączony pod obiekt typu TImage a nie TJPEGImage, a w przypadku TImage działa bez zarzutu.


Cyfrowy Baron napisał(a):
It is not supposed to. Most TGraphic-derived classes, including TBitmap, donot implement the OnProgress event to begin with, as they usually don't need it.

Tego fragmentu chyba też nie przeczytałeś. TJPEGImage dziedziczy po TGraphics i jak sądzę ta wypowiedź też się tyczy tego typu.


przeczytałem, jest ogólny nie o TJPEGImage.

Cyfrowy Baron napisał(a):W plikach pomocy do BCB nie ma nic na temat klasy TJPEGImage.


u mnie jest.

Myślę że wczytywanie/zapisywanie pliku JPG o wielkości 8 MB nie powinno zająć dużo czasu, dekompresja/kompresja (przy pomocy TJPEGImage) już może być widoczna (to oczywiście zależy od sprzętu na którym się testuje - u mnie jest zauważalna).


Zmienione: Pomyliłem TPicture::OnProgress z TImage::OnProgress ale w opisie TPicture::OnProgress jest:

OnProgress is generated by the particular graphic that the picture object contains. Whether OnProgress occurs depends upon the type of graphic in the Graphic property. Some graphics generate this event, others do not. Jpeg images, for example, generate an OnProgress event.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 14
Kompilator: bcb6, Turbo C++ Explorer
    Windows XPOpera

Re: JPEGImage + ProgressBar

Nowy postprzez Cyfrowy Baron » czwartek, 28 stycznia 2010, 12:37

PrzytoczÄ™ jeszcze raz ten zapis:

Zauważ, że OnProgress został podłączony pod obiekt typu TImage a nie TJPEGImage, a w przypadku TImage działa bez zarzutu, ale tylko dla pliku w formacje JPEG, gdyż pliki JPEG mogą być wczytywane progresywnie a bitmapy nie dlatego nie działa w odniesieniu do pliku w formacie BMP. Po części wiec masz rację, że klasa TJPEGImage wywołuje zdarzenie OnProgress, ale nie jest to zdarzenie tej klasy, lecz zdarzenie odziedziczone po klasie TGraphics i działa tylko w połączeniu z obiektem TImage.




Działa dla kompresji/dekompresji (sprawdziłem).


Tu nie chodzi o kompresje czy dekompresje, lecz o wczytywanie i zapisywanie. O ile zdarzenie OnProgress dla TImage i plików w formacie JPEG działa bez zarzutu, o tyle w przypadku samej tylko klasy TJPEGImage już wogóle nie działa.



przeczytałem, jest ogólny nie o TJPEGImage.


Nie jest ogólny, gdyż został umieszczony pod tym cytatem:

after I replaced TImage with TBitmap and some other minor
changes to make it comile, the OnProgress event is not invoked.


Więc tyczy się dokładnie problemu z OnProgress dla wczytywanych bitmap, a jeżeli jeszcze przyjrzysz się pytaniu zadanemu przez Kung Yuan:

I have problem with invoke OnProgress event from TBitmap component.


To nie trudno pojąć, że odpowiedź udzielona Remy Lebeau tyczy się właśnie tego.




Myślę że wczytywanie/zapisywanie pliku JPG o wielkości 8 MB nie powinno zająć dużo czasu, dekompresja/kompresja (przy pomocy TJPEGImage) już może być widoczna (to oczywiście zależy od sprzętu na którym się testuje - u mnie jest zauważalna).


Nie ma znaczenia czy postęp jest widoczny czy nie, gdyby zdarzenie było wywoływane dla TJPEGImage to przy tym kodzie:

Kod: Zaznacz cały
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageProgress(TObject *Sender, TProgressStage Stage,
     BYTE PercentDone, bool RedrawNow, const TRect &R, const AnsiString Msg)
{
  switch(Stage)
  {
   case psStarting: ProgressBar1->Position = 0; break;
   case psRunning:  ProgressBar1->Position = PercentDone; break;
   case psEnding:   ProgressBar1->Position = 100; break;
  }
}
//---------------------------------------------------------------------------


Po zakończeniu wczytywania ProgressBar1 zostałby ustawiony na 100, a nie jest.

Przeprowadziłem test na pliku JPEG o rozmiarze 6 MB i kompresji 50%. Plik wczytywał się ~20 sekund a pasek postępu nie drgnął, podczas gdy przy wczytywaniu do Image wszystko działa prawidłowo. Większych plików klasa TJPEGImage nie chciała wczytać.

Reasumując, o ile dla TImage OnProgress działa prawidłowo, tylko dla plików JPEG niezależnie od stopnia kompresji i wielkości pliku, dla bitmap już nie działa, to w przypadku samej tylko klasy TJPEGImage zdarzenie OnProgress nie jest wywoływane.


Co do RedrawNow to co piszesz niczego nie zmienia, gdy grafika jest wczytywana RedrawNow przyjmuje wartość true, gdy zostanie wczytana lub nie można jej wczytać przyjmuje wartość false. Tyle wystarczy by sterować ProgressBar.



Skoro twierdzisz, że jest inaczej, to podaj działający kod.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: JPEGImage + ProgressBar

Nowy postprzez mervinjmicky » czwartek, 28 stycznia 2010, 12:45

Dzięki Panowie za konstruktywne odpowiedzi. Z wczytywaniem poradziłem sobie - użyłem TImage. Tylko pytanie teraz jak dokonać kompresji w TImage i np zmiany wielkości wczytanego pliku? Bowiem jak próbuję zrobić to za pomocą TCanvas dla TImage to dostaje komunikat, że zmian można dokonywać tylko na plikach bmp. Do tej pory robiłem to tak:
Kod: Zaznacz cały
  TJPEGImage *jpg = new TJPEGImage();
   Graphics::TBitmap *bmp = new Graphics::TBitmap();
   jpg->LoadFromFile(File);
   bmp->Assign(jpg);
   int height=0;
   int procent = (width*100)/bmp->Width;
   height = (bmp->Height*procent)/100;
   bmp->Canvas->StretchDraw(Rect(0, 0, width, height), bmp);
   bmp->Height = height;
   bmp->Width = width;
   jpg->Assign(bmp);
   jpg->CompressionQuality = quality;
   jpg->SaveToFile(temp+"\\\\miniatura1.jpg");
   jpg->Free();
   bmp->Free();
Avatar użytkownika
mervinjmicky
Bladawiec
Bladawiec
 
Posty: 9
Dołączył(a): środa, 27 stycznia 2010, 18:36
PodziÄ™kowaÅ‚ : 3
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
System operacyjny: Kubuntu 9.10
Kompilator: C++ Builder 6
Gadu Gadu: 0
    LinuxChrome

Re: JPEGImage + ProgressBar

Nowy postprzez Cyfrowy Baron » czwartek, 28 stycznia 2010, 12:51

Po wczytaniu pliku JPEG do Image musisz dokonać konwersji na bitmapę:

► patrz serwis: Cyfrowy Baron dziaÅ‚: porady -> grafika

potem wykonujesz operacje na bitmapie, a przed zapisaniem konwertujesz bitmapÄ™ na format JPEG.

Wszystkie operacje wykonuj na obiektach klasy TJPEGImage i Graphics::TBitmap w pamięci, a do Image->Picture kopiuj je tylko poprzez Assign, celem wizualizacji. To czego nie musisz wizualizować, nie kopiuj, czyli możesz wykonać konwersję z JPEG do BITAMPY w pamięci i w pamięci wykonać na bitmapie operację, potem również w pamięci przekonwertować to ponownie na JPEG i dopiero potem przekopiować do Image.

Klasa TJPEGImage nie obsługuje klasy TCanvas.

Konwersji nie możną dokonać poprzez Assign, jak wspomniałem wcześniej ta funkcja służy tylko do kopiowania jednego obiektu na drugi, ale obiekt A do którego się kopiuje obiekt B, musi obsługiwać klasę obiektu A. Klasa TPicture obługuje zarówno klasę TJPEGImage jak i TBitmap, ale TJPEGImage nie obsługuje TBitmap, więc samo kopiowanie nic nie da trzeba przerysować obiekt typu TJPEGImage do obiektu typu TBitmap.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
mervinjmicky
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: JPEGImage + ProgressBar

Nowy postprzez mervinjmicky » czwartek, 28 stycznia 2010, 13:19

Jeszcze raz dzięki. W międzyczasie poradziłem sobie i zrobiłem to tak:
Kod: Zaznacz cały
Graphics::TBitmap * bmp = new Graphics::TBitmap();
bmp->Width = this->Image1->Picture->Width;
bmp->Height = this->Image1->Picture->Height;
bmp->Canvas->Draw(0, 0, this->Image1->Picture->Graphic);
int height = (bmp->Height*(300*100)/bmp->Width)/100;
bmp->Canvas->StretchDraw(Rect(0, 0, 300, height), bmp);
this->Image1->Picture->Assign(bmp);
bmp->Free();
Avatar użytkownika
mervinjmicky
Bladawiec
Bladawiec
 
Posty: 9
Dołączył(a): środa, 27 stycznia 2010, 18:36
PodziÄ™kowaÅ‚ : 3
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
System operacyjny: Kubuntu 9.10
Kompilator: C++ Builder 6
Gadu Gadu: 0
    LinuxChrome


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Aplikacje multimedialne, graficzne

Kto przeglÄ…da forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 1 gość