2011-11-17 3 views
1

J'ai une galerie d'utilisateurs sur le site et il est possible pour les visiteurs de télécharger quelques images. Après l'image de téléchargement doit être redimensionné à certains préréglages prédéfinis. De plus, l'image originale doit être sauvegardée aussi. Tout fonctionne bien pour png et bmp formats d'image. Mais si je télécharge le format gif ou jpeg avec une prédominance d'une couleur, l'image originale téléchargée semble être compressée.Téléchargement d'image sans perte de qualité

Par exemple:

Original:
Original image

Téléchargé:
Uploaded image

Je cherchai thorougly dans google et trouvé quelques exemples comment télécharger l'image à droite. A la fin, je l'ai écrit la méthode suivante:

void UploadImagePreset(Image image, ImageFormat imgFormat, string imgPath) 
{ 
    using (var uploadStream = imageUploader.CreateUploadStream(imagePath)) 
    { 
     var newWidth = image.Width; 
     var newHeight = image.Height; 
     using (var outBitmap = new Bitmap(newWidth, newHeight)) 
     { 
      using (var outGraph = Graphics.FromImage(outBitmap)) 
      { 
       outGraph.CompositingQuality = CompositingQuality.HighQuality; 
       outGraph.SmoothingMode = SmoothingMode.HighQuality; 
       outGraph.PixelOffsetMode = PixelOffsetMode.HighQuality; 
       outGraph.InterpolationMode = InterpolationMode.HighQualityBicubic; 

       var imageRect = new Rectangle(0, 0, newWidth, newHeight); 
       outGraph.DrawImage(image, imageRect); 

       outBitmap.Save(uploadStream, imgFormat); 
      } 
     } 
    } 
} 

Mais il n'a pas aidé. L'image téléchargée était la même que celle décrite ci-dessus. Je tryied de préciser qaulity des résultats d'image comme ceci:

var encoderParameters = new EncoderParameters(); 
var encoderParameter = new EncoderParameter(Encoder.Quality, 100); 
encoderParameters.Param[0] = encoderParameter; 
var encoder = ImageCodecInfo.GetImageEncoders() 
    .Where(e => e.FormatID == imgFormat.Guid) 
    .FirstOrDefault(); 
outBitmap.Save(uploadStream, encoder, encoderParameters); 

Il ne fonctionne pas trop. En outre, lorsque je télécharge une exception d'image jpeg se produit.

Est-il possible de télécharger une image sans la compresser ou la redimensionner? J'ai passé quelques heures à essayer de résoudre ce problème et je suis resté dessus.

+0

Ce n'est pas clair - que fait le téléchargement? Si c'est juste à partir d'un navigateur sans code client supplémentaire, vous devriez obtenir le fichier exact qui est sur le client - à quel point votre problème n'a * rien * à faire avec le téléchargement (ou ASP.NET), et est * juste * à faire avec le redimensionnement. –

+0

J'utilise le contrôle FileUpload sans code client supplémentaire –

+0

Droit, donc d'abord valider que si vous enregistrez le fichier téléchargé - sans le traiter * du tout * - vous vous retrouvez avec exactement le même fichier. Lorsque vous l'avez prouvé, vous pouvez retirer la partie de téléchargement de l'équation. Limitez le problème à la plus petite zone possible. –

Répondre

7

Vous passez l'image téléchargée via la classe Image - il s'agit d'une image nouvelle, basée sur le flux transmis.

Ceci est ensuite enregistré en utilisant certains paramètres par défaut, qui ne reflètent plus l'image d'origine.

Vous devez simplement enregistrer le flux entrant directement sur le disque - cela se traduira par une copie exacte de l'image originale.

Vous aimez cette (.NET 4.0):

using (var uploadStream = imageUploader.CreateUploadStream(imagePath)) 
{ 
    using(var fileStream = new FileStream(imgPath, FileMode.Create)) 
    { 
     uploadStream.CopyTo(fileStream); 
    } 
} 

Ou (avant .NET 4.0):

using (var uploadStream = imageUploader.CreateUploadStream(imagePath)) 
{ 
    using(var fileStream = new FileStream(imgPath, FileMode.Create)) 
    { 
     byte[] buffer = new byte[32768]; 
     int read; 
     while ((read = uploadStream.Read(buffer, 0, buffer.Length)) > 0) 
     { 
      fileStream.Write(buffer, 0, read); 
     } 
    } 
} 

Adapté de this answer.

+0

J'utilise .Net 3.5. La classe Stream n'a pas de méthode CopyTo dans cette version de framework. –

+0

@IgorBlinnikov - Voir ceci pour une autre option: http://stackoverflow.com/questions/230128/best-way-to-copy-between-two-stream-instances-c-sharp – Oded

+0

Merci, Oded. Votre réponse a été très utile. Le problème était que j'ai tout d'abord créé l'objet Image de Stream, puis enregistré Stream. La manipulation d'un objet Stream ajoute du bruit à l'image résultante même si j'enregistre le Stream original, mais pas l'objet Image. Enregistrer le flux dans un fichier directement après le téléchargement (avant de créer un objet Image) résout mon problème. –

1

Je suggère d'utiliser des codecs d'image (votre deuxième exemple) pour la compression d'image sans perte.

Avec une petite modification de code, je suggère que vous essayez ceci:

Bitmap bm = (Bitmap)Image.FromFile(filePath); 
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 
ImageCodecInfo codecInfo = null; 
foreach (ImageCodecInfo codec in codecs) 
{ 
    if (codec.MimeType == "image/jpeg") 
     codecInfo = codec; 
} 
EncoderParameters ep = new EncoderParameters(); 
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100); 
bm.Save("C:\\quality" + x.ToString() + ".jpg", codecInfo, ep); 

Espérons que cela aidera.

+0

Je dois télécharger l'image en l'état. Je ne peux pas changer le format en jpeg. Si l'utilisateur a téléchargé l'image * .png, il doit être enregistré en tant que png. –

+0

Cela a fonctionné parfaitement pour moi. +1 pour le même. :) –

Questions connexes