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: