2010-03-10 7 views
13

Je suis censé écrire un programme qui obtient des images PNG de l'utilisateur, fait quelques modifications simples comme la rotation et les enregistre dans un fichier JAR afin qu'il puisse utiliser les images comme Ressources. Le problème est quand j'ouvre, disons une image de 80kb et l'enregistre ensuite avec C#, j'obtiens une image avec la même qualité mais pour l'espace 130kb. Et parce qu'il doit aller dans un fichier JAR J2ME j'ai vraiment besoin de plus petites tailles, au moins la taille d'origine. J'ai essayé le code ci-dessous mais j'ai découvert plus tard qu'il ne fonctionne que pour les images Jpeg.C# - Comment changer la qualité PNG ou la profondeur de couleur

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); 

C'est là l'image est chargée dans une zone d'image:

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; 
      } 
     } 

Et c'est là, il est en cours d'enregistrement en arrière sans modifications:

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); 

Note: imageFileNames [] est juste un tableau de chaînes qui a certains des noms de fichiers avec lesquels les images doivent être enregistrées.

Toutes les idées seront appréciées et merci d'avance.

+0

La taille du fichier est-elle modifiée lorsque vous réenregistrez l'image sans modifications? –

+0

Salut Jacob, Oui je fais. – Auxiliary

+0

Pouvons-nous voir le code où vous chargez l'image et le code où vous enregistrez l'image? Je ne vois pas de comportement similaire dans mon (simple) test. –

Répondre

10

J'ai pris 4 PNG différents, allant de 2KB à 2.6MB. En utilisant votre code, je les charge et les sauvegarde. Je ne modifie pas l'image en la faisant pivoter ou en la retournant. Les 4 PNG, une fois réenregistrés, ont exactement la même taille. En outre, j'ai pris le PNG de 2,6 Mo, l'ai ouvert dans Photoshop et enregistré deux copies de celui-ci, un entrelacé (réduit à 2,06 Mo), un non entrelacé (réduit à 1,7 Mo.) J'ai ensuite pris chaque de ceux-ci, les a couru à travers votre code et les a sauvés. Les tailles résultantes des deux étaient de retour à l'original 2,6 Mo. Donc, je suppose que les images originales ont été créées avec un logiciel (comme Photoshop) et que ce logiciel a un algorithme de compression optimisé qu'il utilise pour les spécifications PNG que .NET n'utilise pas.

Je me suis trompé avec le EncoderParameter pour la compression, mais il semble n'avoir aucun impact.

+0

Yeb, votre droite. Les images ont été exportées par l'exportateur 3dsMax jsr. Mais savez-vous un moyen de compresser le PNG ou d'abaisser sa qualité afin que je puisse obtenir un résultat similaire à l'exportateur? – Auxiliary

+1

Cela semble prometteur: http://benhollis.net/software/pnggauntlet/ ... Il enveloppe ce PNGOUT de cette page: http://advsys.net/ken/utils.htm –

+1

Ainsi que cela: http: // optipng.sourceforge.net/ –

10

Désolé de soulever une vieille question, mais je résolvais le même problème aujourd'hui et trouvé cette page sur MSDN: "Listing Parameters and Values for All Encoders". J'espère que cela pourrait être utile d'y faire référence.

L'article contient un exemple de programme qui produit EncoderParameter s pris en charge par les codeurs d'images GDI + en stock, et le codeur PNG ne prend en charge aucun paramètre en fonction de cela. Je ne suis pas sûr que si on peut tenir cela pour acquis, ou dans une future version de gdiplus.dll l'encodeur PNG pourrait augmenter le support, et donc on est censé vérifier les capacités de l'encodeur à l'exécution.

Dans tous les cas, l'application d'une transformation explicite sur une image source semble être une approche plus fructueuse; Je ne l'ai pas encore exploré.

+0

Pourquoi GDI + n'aurait-il pas de paramètre de qualité pour le format PNG? Je suppose que je vais devoir utiliser Jpeg alors. : -/ –

+5

@NickGotch, comme 'PNG' est un format sans perte, il ne peut pas avoir de" réglage de qualité "- dans un sens, sa qualité est toujours de 100%. Ce qui manque à l'encodeur GDI +, c'est un bouton contrôlant le compromis vitesse de compression/taux de compression. – kostix

+0

Merci, ça ne change pas ma situation mais c'est bon à savoir. –