2010-03-10 10 views
13

Mam napisać program, który pobiera niektóre obrazy PNG od użytkownika, wykonuje proste zmiany, takie jak obracanie i zapisuje je w pliku JAR, aby mógł używać obrazów jako zasoby. Problem polega na tym, kiedy otwieram, powiedzmy obraz o wielkości 80kb, a następnie zapisz go przy pomocy C#, otrzymuję obraz o tej samej jakości, ale o przestrzeni 130kb. A ponieważ musi wejść do pliku J2ME jar, naprawdę potrzebuję mniejszych rozmiarów, przynajmniej oryginalnego rozmiaru. Próbowałem kodu poniżej, ale później okazało się, że działa tylko dla obrazów JPEG.C# - Jak zmienić jakość PNG lub głębię kolorów

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 
       int j = 0; 
       for (j = 0; j < codecs.Length; j++) 
       { 
        if (codecs[j].MimeType == "image/png") break; 
       } 
       EncoderParameter ratio = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 10L); 
       EncoderParameters CodecParams = new EncoderParameters(1); 
       CodecParams.Param[0] = ratio; 

       Image im; 
       im = pictureBox1.Image; 
       im.Save(address , codecs[j], CodecParams); 

To gdzie obraz jest ładowany do skrzynki obrazku:

private void pictureBox1_DoubleClick(object sender, EventArgs e) 
     { 
      if (openFileDialog1.ShowDialog() == DialogResult.OK) 
      { 
       string address = openFileDialog1.FileName; 
       address.Replace("\\", "\\\\"); 
       Image im = Image.FromFile(address); 
       pictureBox1.Image = im; 
      } 
     } 

I to jest, gdzie jest zapisywany z powrotem bez edycji:

private void generateToolStripMenuItem_Click(object sender, EventArgs e) 
     { 
      if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) 
      { 

       ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 
       int j = 0; 
       for (j = 0; j < codecs.Length; j++) 
       { 
        if (codecs[j].MimeType == "image/png") break; 
       } 
       EncoderParameter ratio = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 10L); 
       EncoderParameters CodecParams = new EncoderParameters(1); 
       CodecParams.Param[0] = ratio; 

       string address = folderBrowserDialog1.SelectedPath; 
       address = address + "\\"; 
       address.Replace("\\", "\\\\"); 

       Image im; 
       im = pictureBox1.Image;    
       im.Save(address + imageFileNames[1], codecs[j], CodecParams); 

UWAGA: imageFileNames [] jest po prostu tablicą ciągów, która zawiera niektóre nazwy plików, do których obrazy muszą być zapisane.

Wszelkie pomysły zostaną docenione i z góry dziękujemy.

+0

Czy zmienia się rozmiar pliku po ponownym zapisaniu obrazu bez wprowadzania zmian? –

+0

Cześć Jacob, tak, robię. – Auxiliary

+0

Czy widzimy kod, w którym ładujemy obraz i kod, w którym zapisujesz obraz? Nie widzę podobnego zachowania w moim (prostym) teście. –

Odpowiedz

10

Zrobiłem 4 różne pliki PNG o rozmiarach od 2KB do 2.6MB. Korzystając z kodu, ładuję je i zapisuję. Nie modyfikuję obrazu poprzez obracanie lub odbijanie. Wszystkie 4 pliki PNG, po ponownym zapisaniu, mają dokładnie taki sam rozmiar.

Dodatkowo pobrałem 2,6MB PNG, otworzyłem go w Photoshopie i zapisałem dwie kopie, jedną przeplecioną (zmniejszoną do 2.06MB), jedną bez przeplotu (zredukowaną do 1.7MB). Następnie wziąłem każdą z nich, przeprowadził je przez twój kod i zapisał je. Uzyskane rozmiary obu z nich powróciły do ​​pierwotnego rozmiaru 2.6 MB.

Zgaduję więc, że oryginalne obrazy zostały utworzone za pomocą oprogramowania (np. Photoshop), a to oprogramowanie ma zoptymalizowany algorytm kompresji, którego używa w specyfikacji PNG, której nie używa .NET.

Połączyłem z EncoderParameter dla kompresji, ale wydaje się, że nie ma ono żadnego wpływu.

+0

Yeb, twoja prawa. Obrazy zostały wyeksportowane przez eksportera jsr 3dsMax. Ale czy znasz sposób na skompresowanie pliku PNG lub obniżenie jego jakości, aby uzyskać podobny wynik do eksportera? – Auxiliary

+1

To wygląda obiecująco: http://benhollis.net/software/pnggauntlet/ ... To opakowuje tego PNGOUT z tej strony: http://advsys.net/ken/utils.htm –

+1

Podobnie jak to: http: // optipng.sourceforge.net/ –

10

Przepraszam za przypomnienie starego pytania, ale rozwiązałem ten sam problem i znalazłem tę stronę na stronie MSDN: "Listing Parameters and Values for All Encoders". Mam nadzieję, że warto tam o tym wspomnieć.

Artykuł zawiera przykładowy program, który wyprowadza EncoderParameter s obsługiwane przez kodery obrazu GDI +, a koder PNG nie obsługuje żadnych parametrów zgodnie z nim.

Nie jestem pewien, czy można przyjąć to za pewnik, lub w jakiejś przyszłej wersji gdiplus.dll koder PNG może zyskać większe wsparcie, a więc należy sprawdzić możliwości enkodera w czasie wykonywania.

W każdym przypadku zastosowanie pewnej wyraźnej transformacji na obrazie źródłowym wydaje się być bardziej owocnym podejściem; Nie zbadałem jeszcze tego.

+0

Dlaczego GDI + nie ma ustawienia jakości dla PNG? Chyba będę musiał użyć Jpeg. : -/ –

+5

@NickGotch, ponieważ 'PNG' jest formatem bezstratnym, nie może mieć" ustawienia jakości "- w pewnym sensie jego jakość zawsze wynosi 100%. Wygląda na to, że brakuje kodera GDI +, który kontroluje wyłączenie kompresji prędkości kodowania/kompresji. – kostix

+0

Dzięki, nie zmienia to mojej sytuacji, ale dobrze wiedzieć. –

Powiązane problemy