Artykuły

A A A
Drukuj Ekportuj do PDF
Opublikowane: 2005.02.18 1:34 | User 131096 | Aktualizacja: 2010.01.21 2:04

Varia: Eksperymenty z kompresją JPG

Podczas przeczesywania dysku i zastanawiania się, co można by z niego wyrzucić, czasami spotykamy rózne ciekawostki... Znalazłem jeden ze swoich starych programów do testowania kompresji JPG.

Jak to fajnie czasami znaleźć coś, o czym się zapomni, że istnieje. Założę się, że wielu spośród Czytelników miało niejednokrotnie podobną zagwozdkę co i ja. Na pewno wielu z Was zdarzyło się podczas przeglądania staroci natknąć się na swoje archiwum kodu, z ciekawości obejrzeć, co się kiedyś "spłodziło" i z uśmiechem przeglądać swój kod i myśleć: "Jej, kiedyś naprawdę nic nie umiałem, teraz jestem do przodu" :).

Chciałbym oddać Wam jeden z drobnych programików, które w ten sposób odnalazłem. W zasadzie wszystko znajduje się w załączniku, a cały program ogranicza się do jednego istotnego fragmentu kodu. W tym fragmencie kodu korzystałem z następujących przestrzeni nazw:

[Kod C#]

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Drawing.Imaging;
using System.IO;

A oto i sam kod:

[Kod C#]

private void ImageQualityTrackBar_Scroll(object sender, System.EventArgs e)
{
 if(originalBitmap != null)
 {
  if(crunchedBitmap != null)
  {
   crunchedBitmap.Dispose();
   crunchedBitmap = null;
  }

  Stream tmpStream = new MemoryStream();
    
  ImageCodecInfo  myImageCodecInfo = null;
  Encoder    myEncoder;
  EncoderParameter myEncoderParameter;
  EncoderParameters myEncoderParameters;

  ImageCodecInfo[] encoders;
  encoders = ImageCodecInfo.GetImageEncoders();
  for(int j = 0; j < encoders.Length; j++)
   if(encoders[j].MimeType == "image/jpeg")
   {
    myImageCodecInfo = encoders[j];
    break;
   }

  myEncoder = Encoder.Quality;

  myEncoderParameters = new EncoderParameters(1);
  myEncoderParameter = new EncoderParameter(myEncoder, ImageQualityTrackBar.Value);
  myEncoderParameters.Param[0] = myEncoderParameter;
  originalBitmap.Save(tmpStream, myImageCodecInfo, myEncoderParameters);

  crunchedBitmap = new Bitmap(tmpStream);
  CrunchedPicture.Image = crunchedBitmap;

  LabelQuality.Text = "Quality: " + ImageQualityTrackBar.Value.ToString() + "%";
  LabelQuality.Text += "\n" + tmpStream.Length.ToString() + " bytes";
 }
}

Ci, którzy mają jakieś doświadczenie z .NET'em zaczną się śmiać, nowicjusze zaczną się drapać po głowie. Już po kolei wyjasniam... To jest metoda, która obsługuje wydarzenie występujące przy przesuwaniu TrackBara. TrackBar odpowiada za określenie jakości obrazu, jaki chcemy podejrzeć, bo to był główny zamysł aplikacji - mieć wyobrażenie o tym, ile traci na jakości obraz przy kompresji.

Po pierwsze - jeśli istnieje (został załadowany) oryginalny obraz i istnieje spakowany obraz, to przy każdym przesunięciu TrackBara wypadałoby wyrzucić ten obraz z pamięci - i tak zostanie zastąpiony kolejną wersją skompresowaną z innymi parametrami. Te bogato nazwane "parametry" to po prostu jakość pliku, która zależy od pozycji suwaka na formularzu. Ale to wybieganie w przyszłość.

Po drugie - w systemie Windows, wspomaganym mocno przez .NET Framework, mamy do dyspozycji wiele różnych kodeków obrazu. W tej chwili skupiamy się na kodeku do JPG, więc dobijamy sie do listy dostępnych kodeków i szukamy takiego, który potrafi skompresować obraz do "image/jpeg". Odbywa się to na zasadzie przeszukiwania listy kodeków i złapania i zapamiętania tego, który spełnia nasze wymagania.

Aby kodek mógł sprawnie działać - należy podac mu parametry, z jakimi ma wykonywać zamianę formatów. Tworzymy więc odpowiedni parametr, odpowiadający za jakośc obrazu, a uzależniony od wartości TrackBara i... Zapisujemy do całkiem wygodnego obiektu klasy MemoryStream to, jak by wyglądał plik ze skompresowanym obrazem. Następnie odczytujemy ten plik i odtworzoną z niego bitmapę ustawiamy jako obraz wyświetlany przez naszą kontrolkę. Ot cała teoria :).

Cały kod załączony do tego artykułu jest w postaci identycznej, jaką miał w chwili archiwizacji. Cały "projekt" powstał w ciągu jednego dnia, 4 grudnia 2004 roku. Od tej pory minął ponad rok i udało mi się nauczyć kilku rzeczy o .NET'cie. Załączony kod nie jest idealny, nie pokazuje najlepszych praktyk .NET'owych. Dlaczego więc zdecydowałem się na jego publikację, pomimo, że nie jest doskonały? Po to, by zachęcić nowicjuszy do własnych eksperymentów i prób poznania .NET'a. C# i .NET to bardzo fajne środowisko do pracy i jak okazuje się - do programistycznej zabawy. Owocem jednej z moich zabaw jest ten program, no i po pewnym czasie - ten artykuł.

Chcę zaprosić Was do dyskusji na temat tego artykułu - chętnie podzielę się z Wami wiedzą, którą udało mi się zdobyć przez ten rok, chętnie przyznam się do wszystkich pomyłek, które popełniłem w tym programie. Chętnie opowiem o swoich programistycznych "grzeszkach" i mam nadzieję, że lektura tego artykułu i komentarzy pomoże komuś nauczyć się czegoś o .NET'cie :).

PS. Pozwoliłem sobie na jedną edycję w archiwum ZIP. Usunąłem z niego pewien znany obrazek przedstawiający panią w kapeluszu. Pani ma na imię Lena i jest jednym z klasycznych obrazów demonstracyjnych we wszelkich publikacjach dotyczących grafiki komputerowej (kto z Was wie dlaczego?). Dla ciekawych załączam link do obrazka: http://artengine.ca/gridflow/latest/images/lena.jpg, oraz do "googlowego niesmiertelnika", dzięki któremu można ją znależć, nawet jak padnie strona do której wskazuje pierwszy link: http://images.google.com/images?svnum=50&hl=en&lr=&safe=off&q=lena.jpg

Zapraszam wszystkich do dyskusji i do własnych wynurzeń programistycznych :)

Załączniki:


Podobne artykuły

Komentarze 6 Masz uwagi do tej strony? Napisz

User 131096 2010.01.21 1:10
0 oceń pozytywnie   oceń negatywnie 0
avatar
 
Miło popatrzeć na oceny - widzę, że na portal zaglądają jedynie sami eksperci i nie ma sensu publikować takich wygrzebanych starych drobnostek ;)
User 79600 2010.01.21 1:10
0 oceń pozytywnie   oceń negatywnie 0
avatar
 
Ja wiem dlaczego Lena, ja wiem dlaczego! :-D Ta pani to playmate z jednego z baaaardzo starych numerow amerykanskiej edycji Playboya. Jej zdjecie "od ramion w gore" zostalo uzyte jako probka w jednej z pierwszych publikacji na temat filtrowania obrazu. To tak jak obecnie wszystkie prace na temat geometrii roslin i wizualizacji w botanice powoluja sie na systemy Lindenmayera opracowywane przez lata przez Lindenmayera i Prusinkiewicza - obecnie nie wypada nie zacytowac Prusinkiewicza tak jak nie wypada filtrowac roznych problek i pominac Lene. ;]
User 79623 2010.01.21 1:10
0 oceń pozytywnie   oceń negatywnie 0
avatar
 

hmm ja sądzę, że takie arty też są potrzebne.. w końcu to, że początkujacy się nie udzielają (za bardzo) to nie znaczy, że trzeba ich olać i nie publikować nic dla nich.

Vigrid i tak Cię kochamy ;)

 

User 131096 2010.01.21 1:10
0 oceń pozytywnie   oceń negatywnie 0
avatar
 

Raczej nazwanie tego "artykułem" to przesada, patrząc na to co na portalu. Bardziej to pasuje jako ciekawostka, którą chciałem się podzielić. A do dyskusji zapraszam chociażby po to, żeby ktoś mnie objechał za to, jaki kod podesłałem ;)

User 79543 2010.01.21 1:10
0 oceń pozytywnie   oceń negatywnie 0
avatar
 
Nawet jeśli to "tylko" ciekawostka - to została napisana samodzielnie - a zawsze to znacznie bardziej wartościowe niż nieudolna zżyna z MSDNa. ;-)
User 131096 2010.01.21 1:10
0 oceń pozytywnie   oceń negatywnie 0
avatar
 
Jako kolejną ciekawostkę planuję artykuł ze zbiorem linków. To tak, żeby podwyższyć poziom zabawy ekspertów na portalu :)

Dodaj komentarz

avatar

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.

Autor User 131096
avatar
 

Załóż konto
CodeGuru to miejsce dla każdego programisty. Przez lata portal rozwijany był siłami społeczności i to właśnie społeczność programistów jest tutaj najważniejsza. CG od wielu lat gromadzi wokół siebie coraz większą grupę pasjonatów. Warto być jej częścią!

Dowiedz się więcej o CodeGuru

Geek Club - Windows Phone

 

MetroOne

Idź na górę strony