2009-07-21 6 views
2

J'ai écrit une classe d'assistance PhotoEditor simple pour redimensionner et recadrer les images téléchargées sur mon site Web. Tout fonctionne mais je vois une qualité insatisfaisante lorsque l'image est sauvegardée dans un fichier. J'ai lu sur les différents paramètres que vous pouvez modifier ci-dessous est ma configuration pour le redimensionnement, le recadrage est identique.Redimensionnement de la réduction de la qualité d'image

public Image ResizeImage(Image imgToResize, Size size) 
    { 
     int sourceWidth = imgToResize.Width; 
     int sourceHeight = imgToResize.Height; 

     float nPercentW = (size.Width/(float) sourceWidth); 
     float nPercentH = (size.Height/(float) sourceHeight); 

     float nPercent = nPercentH < nPercentW ? nPercentH : nPercentW; 

     var destWidth = (int) (sourceWidth*nPercent); 
     var destHeight = (int) (sourceHeight*nPercent); 

     var src = imgToResize; 

     using (var dst = new Bitmap(destWidth, destHeight, imgToResize.PixelFormat)) 
     { 
      dst.SetResolution(imgToResize.HorizontalResolution, imgToResize.VerticalResolution); 

      using (var g = Graphics.FromImage(dst)) 
      { 
       var mime = GetMimeType(imgToResize); 
       ImageFormat format; 
       if (mime == "image/gif" || mime == "image/png") 
       { 
        //convert all gif to png, better resize quality 
        g.SmoothingMode = SmoothingMode.AntiAlias; 
        g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
        g.DrawImage(src, 0, 0, dst.Width, dst.Height); 
        format = ImageFormat.Png; 
       } 
       else 
       { 
        //jpeg 
        g.CompositingQuality = CompositingQuality.HighQuality; 
        g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
        g.SmoothingMode = SmoothingMode.HighQuality; 
        g.PixelOffsetMode = PixelOffsetMode.HighQuality; 
        format = ImageFormat.Jpeg; 
       } 
       g.DrawImage(src, 0, 0, dst.Width, dst.Height); 

       // At this point the new bitmap has no MimeType 
       // Need to output to memory stream 
       var m = new MemoryStream(); 
       dst.Save(m, format); 

       var img = Image.FromStream(m); 

       return img; 
      } 
     } 
    } 

Comme vous pouvez le voir, je suis en utilisant les réglages suggérés pour l'interpolation, etc. Lissage Je sauve aussi le jpeg avec la qualité 100.

L'image résultante a flou perceptible et même des objets lors du redimensionnement jusqu'à un modeste 75% de sa taille d'origine. J'ai regardé autour et c'est la manière recommandée. J'ai trouvé un moyen simpliste de redimensionner et j'ai décidé d'essayer. Étonnamment, cela produit une image beaucoup plus agréable, même si elle est un peu plus grande ~ 30% plus grande de l'empreinte de la mémoire.

Ma question est, quelle est la différence et quel paramètre est-il manquant sur ma routine de redimensionnement qui pourrait expliquer le résultat le plus laid. Id aime obtenir ma routine de redimensionnement pour produire exactement le même résultat que le redimensionnement simple.

Votre aide est grandement appréciée. C'est ma première incursion dans le traitement d'image.

EDIT

Simple Resize (82KB)

simple http://img189.imageshack.us/img189/2137/simpleresize.jpg

Mon Resize (55KB)

complex http://img12.imageshack.us/img12/4023/complexresize.jpg

+1

Le dst.Save (m, format); ressemble à votre problème. Vous l'encodez en jpeg, avec une qualité par défaut (pas 100%), puis en le décodant immédiatement sur une image. Dst est déjà une Image (la classe Bitmap hérite de Image), donc vous pouvez simplement la retourner telle quelle. – David

+0

Salut David. Tu avais raison. Mon raisonnement derrière cette étape était que le type Mime faisait partie de l'image résultante. Je stocke temporairement l'image dans la session et je voulais pouvoir la récupérer plus tard. Si vous mettez à jour votre réponse, indiquez la réponse. – madcapnmckay

Répondre

2

Ma première pensée a été que l'encodeur jpeg de .NET utilise chroma sous-échantillonnage même à la plus haute qualité settin g, les informations de couleur sont donc stockées à la moitié de la résolution. Le réglage est codé en dur pour autant que je sache. Mais cela n'expliquerait pas pourquoi vous obtiendriez une meilleure qualité dans le deuxième exemple. Sauf peut-être dans la seconde, il n'a pas utilisé l'anti-crénelage, donnant une image plus nette (mais de qualité inférieure) et les artefacts sont passés inaperçus.

Édition: La commande dst.Save (m, format); ressemble à votre problème. Vous l'encodez en jpeg, avec une qualité par défaut (pas 100%), puis en le décodant immédiatement sur une image. dst est déjà une image (classe Bitmap hérite de l'image), de sorte que vous pouvez simplement le retourner tel quel

+0

Merci pour votre réponse rapide. J'ai essayé de changer les paramètres AA pour voir si ça aide mais ça ne semble pas être la cause des artefacts. Je retourne et quatrième entre le redimensionnement simple et le complexe et les artefacts ne sont présents que sur le complexe. – madcapnmckay

+0

Quelqu'un sait quelle est la qualité par défaut? – Liam

4

J'ai trouvé cet exemple extrait de code (désolé, je l'ai oublié la source) qui pourraient vous aider:

// Create parameters 
EncoderParameters params = new EncoderParameters (1); 

// Set quality (100) 
params.Param[0] = new EncoderParameter(Encoder.Quality, 100); 

// Create encoder info 
ImageCodecInfo codec = null; 
foreach (ImageCodecInfo codectemp in ImageCodecInfo.GetImageDecoders()) 
{ 
    if (codectemp.MimeType == "image/jpeg") 
    { 
     codec = codectemp; 
     break; 
    } 
} 

// Check 
if (codec == null) 
    throw new Exception("Codec not found for image/jpeg"); 

// Save 
image.Save(filename, codec, params); 
+0

Nice. Il préserve la qualité de l'image et réduit la taille de l'image. – Gabriel

Questions connexes