CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Zmiana rozmiaru i jakości pliku JPG

Zmiana rozmiaru i jakości pliku JPG

problemy z tworzeniem aplikacji graficznych oraz audio i wideo

Zmiana rozmiaru i jakości pliku JPG

Nowy postprzez Gazunio » wtorek, 24 sierpnia 2010, 13:39

Witam.
Wykonuję program, który pozwoli na zmianę rozmiaru pliku JPG i potem, na jego zapisanie. Zadanie niby bardzo proste. Wykonuję je zgodnie z odpowiednią poradą na ► patrz serwis: Cyfrowy Baron. Ładnie wszystko działa, poza jednym elementem - jakością zmniejszonego pliku. Chodzi tutaj o zmniejszanie zdjęć aparatu do formatu np. 800x600. Plik się zapisuje w takim rozmiarze, ale jego jakość jest tragiczna - jak kiepsko wykonany efekt "komiksowy".
Oto obrazek, który zmniejszyłem i zapisałem przy pomocy popularnego programu graficznego:
Obrazek
A tutaj zapisany w moim programie:
Obrazek
Jest duża różnica - która nie jest do zaakceptowania.
Nie znalazłem też opcji, by wybierać jakość zapisywanego pliku - w Delphi jest to przykładowo:
KOD cpp:     UKRYJ  
JPG.Performance := jbBestQuality;

KOD cpp:     UKRYJ  
JPG.CompressionQuality := 100;


Jak można to wykonać - poprawić?
Avatar użytkownika
Gazunio
Bladawiec
Bladawiec
 
Posty: 32
Dołączył(a): środa, 13 maja 2009, 18:40
Podziękował : 3
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2009
Gadu Gadu: 5147883
    Windows 7Firefox

Re: Zmiana rozmiaru i jakości pliku JPG

Nowy postprzez Cyfrowy Baron » wtorek, 24 sierpnia 2010, 15:19

Skalowanie obrazka z dobrym skutkiem można przeprowadzić tak:

KOD cpp:     UKRYJ  
 TJPEGImage *jpgFile = new TJPEGImage();

 jpgFile->Scale =  jsFullSize;
 jpgFile->LoadFromFile("c:\\image.jpg");


 /* algorytm skalujący celem zachowania proporcji obrazka */
 double ws = 0.0;
 if(jpgFile->Width > jpgFile->Height)
 ws = (double)jpgFile->Width / (double)jpgFile->Height;
 else ws = (double)jpgFile->Height / (double)jpgFile->Width;


 // zmiana rozmiaru Widht na 800 pikseli
 double jpgWidth  = 800;
 double jpgHeight = jpgWidth / ws;

 Graphics::TBitmap *bmpFile = new Graphics::TBitmap;
 bmpFile->Width  = (int)jpgWidth;
 bmpFile->Height = (int)jpgHeight;

 bmpFile->Canvas->StretchDraw(Rect(0, 0, bmpFile->Width, bmpFile->Height), jpgFile);

 jpgFile->CompressionQuality = 100;
 jpgFile->Assign(bmpFile);

 jpgFile->SaveToFile("c:\\new image.jpg");

 delete jpgFile;
 delete bmpFile;


To skalowanie nie pozwala jednak na sterowanie efektem skalowania, a np. powiększając obrazek powinno się go rozmywać, a zmniejszając wyostrzać by uzyskać lepszy efekt. Można w tym celu stworzyć sobie taka funkcję:

KOD cpp:     UKRYJ  
#include "Math.hpp"

void __fastcall BlurImage(Graphics::TBitmap *Bitmap)
{
 int flt[] = {2, 2, 2, 2, 24, 2, 2, 2, 2}; // wartości sterujące efektem - tutaj raczej rozmycie
 int Div = 43; // wartości sterujące efektem - tutaj raczej rozmycie - skala

 int XX[3];

 BYTE   *ptr, *ptru, *ptrd, *ptr1;

 Graphics::TBitmap   *tmpBitmap = new   Graphics::TBitmap();

 Bitmap->PixelFormat = pf24bit;

 tmpBitmap->Assign(Bitmap);
 tmpBitmap->PixelFormat = pf24bit;

 for(int y = 1; y < tmpBitmap->Height - 1; y++)
 {
  ptr  = (BYTE *) Bitmap->ScanLine[y];
  ptr1 = (BYTE *) tmpBitmap->ScanLine[y];
  ptru = (BYTE *) tmpBitmap->ScanLine[y-1];
  ptrd = (BYTE *) tmpBitmap->ScanLine[y+1];

  for(int x = 3; x < (tmpBitmap->Width - 1) * 3; x += 3)
  {
   XX[0] = 0; XX[1] = 0; XX[2] = 0;

   for (int i1 = -1; i1 <= 1; i1++)
    for(int j1 = 0; j1 < 3; j1++)
     XX[j1] += ptr1[x + 3 * i1 + j1] * flt[4 + i1];

   for(int i2 = -1; i2 <= 1; i2++)
    for(int j2 = 0; j2 < 3; j2++)
     XX[j2] += ptru[x + 3 * i2 + j2] * flt[1 + i2];

   for(int i3 =- 1; i3 <= 1; i3++)
    for(int j3 = 0; j3 < 3; j3++)
     XX[j3] += ptrd[x + 3 * i3 + j3] * flt[7 + i3];

   for(int i4 = 0; i4 < 3; i4++)
   {
    XX[i4] = XX[i4] / Div;
    XX[i4] = Max(XX[i4], 0);
    XX[i4] = Min(XX[i4], 255);
    ptr[x + i4] = XX[i4];
   }
  }
 }
 delete tmpBitmap;
}


Wywołanie funkcji odbywa się po zmianie rozmiaru obrazka:

KOD cpp:     UKRYJ  
 bmpFile->Canvas->StretchDraw(Rect(0, 0, bmpFile->Width, bmpFile->Height), jpgFile);
 BlurImage(bmpFile);
 jpgFile->CompressionQuality = 100;
 jpgFile->Assign(bmpFile);


Zmieniając wartości można zmienić stopień rozmycia:

KOD cpp:     UKRYJ  
 int flt[] = {1, 1, 1, 1, 20, 1, 1, 1, 1};
 int Div = 20;


Można też uzyskać wyostrzenie:

KOD cpp:     UKRYJ  
 int flt[] = {0, 0, 0, -1, 4, -1, 0, -1, 0};
 int Div = 1;


a tak np. wyostrzenie łagodniejsze:

KOD cpp:     UKRYJ  
 int flt[] = {-1, 0, 0, -1, 6, -1, 0, 0, 0};
 int Div = 3;


i np. bardzo łagodne wyostrzenie:

KOD cpp:     UKRYJ  
 int flt[] = {0, 0, 0, -1, 10, -1, 0, 0, 0};
 int Div = 7;


Jak widzisz możliwości sterowania tym filtrem jest dużo. Możesz nie tylko rozmywać i wyostrzać obrazek, ale również sterować jego kontrastem i nasyceniem.

Dla celów testowych proponuję stworzyć specjalny formularz konfiguracyjny, coś w tym stylu:

filtr.png
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Gazunio
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: Zmiana rozmiaru i jakości pliku JPG

Nowy postprzez Gazunio » wtorek, 24 sierpnia 2010, 16:27

Wielkie dzięki za pomoc. Wystarczyło samo skalowanie i zapisywanie. Jest taki sam efekt jak w przypadku normalnego programu graficznego. Jeszcze raz - wielkie dzięki za pomoc. Już połączyłem ten kod z elementami CSpin do rozmiaru obrazka i ScrollBarem dla ustawiania jakości zdjęć.
Avatar użytkownika
Gazunio
Bladawiec
Bladawiec
 
Posty: 32
Dołączył(a): środa, 13 maja 2009, 18:40
Podziękował : 3
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2009
Gadu Gadu: 5147883
    Windows 7Firefox

Re: Zmiana rozmiaru i jakości pliku JPG

Nowy postprzez Cyfrowy Baron » wtorek, 24 sierpnia 2010, 16:29

Jest taki sam efekt jak w przypadku normalnego programu graficznego.


To zależy jakiego programu używasz. Photoshop np. podczas zmniejszania rozmiaru obrazka umożliwia jego wyostrzenie, co znacznie poprawia jego jakość.
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: Zmiana rozmiaru i jakości pliku JPG

Nowy postprzez borysewicz » piątek, 1 października 2010, 19:20

Dołączę się do tematu z podobnym problemem.
Mi chodzi o zmniejszenie wagi zdjęcia poniżej mamy kod który robi zrzut ekranu do JPEG on przynajmniej u mnie zajmuje 231 KB co można zrobić by zmniejszyć to do powiedzmy 50 KB?

Może przekonwertować na format GIF?


PS
Próbowałem też ze zmiana skali obrazka ale po tym nie można odczytać tekstu.
A może jest coś takiego co robi zrzut ekranu tak jakby monitor miał mniejszą rozdzielczość niż w rzeczywistości to by dało dobra jakość i mniejszą wage.

KOD cpp:     UKRYJ  
void __fastcall TForm2::Button2Click(TObject *Sender)
{
TCanvas *pCanvas = new TCanvas();
 Graphics::TBitmap *Bmp = new Graphics::TBitmap;

 pCanvas->Handle = GetDC(0);
 Bmp->Width  = Screen->Width;
 Bmp->Height = Screen->Height;
 Bmp->Canvas->CopyRect(Rect(0, 0, Bmp->Width, Bmp->Height), pCanvas, Rect(0, 0, Bmp->Width, Bmp->Height));

 std::auto_ptr<TJPEGImage> jpegImg(new TJPEGImage());
jpegImg->Assign(Bmp);

 jpegImg->SaveToFile("C:\\111.jpg");
 ReleaseDC(0, pCanvas->Handle);

 delete pCanvas, Bmp;
}
 
Avatar użytkownika
borysewicz
Bladawiec
Bladawiec
 
Posty: 8
Dołączył(a): czwartek, 23 września 2010, 09:53
Podziękował : 5
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: Embarcadero RAD Studio 2010
C++ Builder 2010
Gadu Gadu: 0
    Windows XPOpera

Re: Zmiana rozmiaru i jakości pliku JPG

Nowy postprzez Cyfrowy Baron » piątek, 1 października 2010, 19:43

Zmniejsz jakość zdjęcia:

KOD cpp:     UKRYJ  
 jpgFile->CompressionQuality = 100; // zakres od 1 do 100


CompressionQuality określa stopień kompresji formatu JPEG w procentach, czyli 100 to najlepsza jakość i największy plik, gdyż jest to najniższy stopień kompresji, a 1 to najgorsza jakość i najmniejszy plik, gdyż jest to najwyższy stopień kompresji.

Przeczytaj cały wątek, wtedy nie będziesz zadawał pytań na które odpowiedź już się znajduje w wątku.



Może przekonwertować na format GIF?


A masz jakąś bibliotekę do obsługi tego formatu, bo w RAD Studio standardowo taka biblioteka nie występuje. Co innego gdybyś chciał to zrobić w GDI+, o czym przeczytasz w serwise Cyfrowy Baron - dział: porady -> grafika -> Wyświetlanie grafiki z wykorzystaniem biblioteki gdiplus.dll GDI+ - pod-temat: Konwersja plików z jednego formatu na inny.



A może jest coś takiego co robi zrzut ekranu tak jakby monitor miał mniejszą rozdzielczość niż w rzeczywistości to by dało dobra jakość i mniejszą wage.


Rozdzielczość to rozdzielczość, nie ma znaczenia czy to rozdzielczość grafiki czy ekranu.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
borysewicz
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


  • 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ść