2016-02-03 1 views
6

Je veux une fonction qui réduira la taille de l'image.Réduire la taille de l'image en C#

La fonction doit prendre l'URL de l'image, vérifier est la taille de l'image 4MB ou plus grand et si elle est alors redimensionner à l'amant puis 4 Mo et retourner des octets.

J'ai méthode suivante:

public byte[] ResizeImage(string url) 
{ 
    var uri = new Uri(url); 
    var c = new WebClient(); 
    var oldImgStream = new MemoryStream(c.DownloadData(uri)); 

    if (oldImgStream.Length <= 4194304) 
    { 
     return oldImgStream.ToArray(); 
    } 

    using (var oldImage = new Bitmap(oldImgStream)) 
    using (var newImageStream = new MemoryStream()) 
    { 
     var format = oldImage.RawFormat; 
     float resizePercent = (float)4194304/oldImgStream.Length; 
     var newImage = ResizeImageByPercent(oldImage, resizePercent); 

     newImage.Save(newImageStream, format); 

     return newImageStream.ToArray(); 
    } 
} 

public static Bitmap ResizeImageByPercent(Bitmap image, float resizePercent) 
{ 
    //Set minimum resizePercentage to 80% 
    resizePercent = resizePercent > 0.8 ? (float)0.8 : resizePercent; 

    int newWidth = (int)(image.Width * resizePercent); 
    int newHeight = (int)(image.Height * resizePercent); 

    var newImage = new Bitmap(newWidth, newHeight); 
    using (var graphics = Graphics.FromImage(newImage)) 
    { 
     graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 
     graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 
     graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 
     graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; 
     graphics.FillRectangle(Brushes.Transparent, 0, 0, newWidth, newHeight); 
     graphics.DrawImage(image, 0, 0, newWidth, newHeight); 
     return newImage; 
    } 
} 

Mais cela ne fonctionne pas bien.

J'ai une image jpg comme exemple.

La taille de l'image est un peu plus de 4 Mo (4194587 octets). La résolution de l'image est de 2272 x 1704.

Donc quand j'essaye de redimensionner cette image avec ma méthode ci-dessus. Il calcule d'abord « resizePercentage » comme:

float resizePercent = (float)4194304/oldImgStream.Length; 
resizePercent = (float)4194304/4194587; 
resizePercent = 0.9999325 //(99.99325%) 

Mais parce que je l'ai mis au moins resizePercent il sera fixé à 0,8 (80%).

resizePercent = 0.8; 

Puis il calculera la nouvelle largeur et hauteur avec ce resizePourcent.

La nouvelle résolution sera: 1817 x 1363 et l'image sera redimensionnée à une nouvelle résolution. Mais après qu'il est enregistré pour diffuser et lire des octets, il renvoie une image encore plus grande. Le site de l'image retournée est "5146056 bytes" 5MB

Alors est-ce que quelqu'un a une idée de comment implémenter ceci, ou qu'est-ce qui ne va pas dans ma méthode afin de rendre une image plus grande même si la résolution est réduite.

je devrais être en mesure de réduire la taille des images png, jpg et gif

+0

Vous ne connaissez pas la qualité de la compression jpg appliquée lorsque vous recevez l'image. Alors peut-être que vous enregistrez l'image avec une qualité supérieure (c'est-à-dire moins de compression) que l'image originale. Le problème persiste-t-il lorsque vous travaillez avec des images bmp? – wertzui

+0

Si votre image de test est un fichier JPEG, il a probablement été compressé avec un taux de compression supérieur à celui utilisé par défaut par .NET. Parce que les JPEG utilisent une compression avec perte, il existe une large gamme de taux de compression disponibles; ils détermineront à quel point l'image résultante est granuleuse. Pour les fichiers PNG, qui sont sans perte, il est toujours possible que l'image originale ait été compressée par un meilleur algorithme que celui utilisé par .NET. Etc. – adv12

Répondre

1

Il n'y a pas une une à une corrélation entre la taille du fichier image et la résolution, lorsqu'ils traitent avec des bitmaps compressés. Cette corrélation existe pour un vrai bitmap (BMP, par exemple), puisque 1 pixel est toujours égal à un nombre défini d'octets (basé sur l'espace de couleurs). Cependant, lorsque l'on parle de bitmaps compressés, comme JPEG, la taille du fichier est basée sur l'efficacité de la compression (combien de couleurs doivent être codées globalement, combien de pixels peuvent être combinés en fonction de la même couleur, ou combien le dithering peut être fait pour créer plus de pixels de la même couleur qui peuvent être combinés). Cela peut finir par être moins avec une image de résolution inférieure, mais il pourrait tout aussi bien rester inchangé ou même augmenter, en fonction de l'efficacité de la compression originale et de l'effet global d'une moindre quantité de pixels sur l'efficacité de la compression . Long et court, vous ne pouvez pas simplement appliquer une réduction en pourcentage simple de la résolution pour garantir une certaine taille de fichier. Le mieux que vous puissiez vraiment, c'est de diminuer graduellement la résolution, en testant la taille du fichier à chaque itération, jusqu'à ce qu'elle soit inférieure à votre seuil, en supposant qu'elle soit effectivement inférieure au seuil. Avec 4 Mo pour jouer avec, il est concevable une certaine résolution qui serait certainement en dessous de cela, mais où ce point se trouve est pratiquement impossible à calculer.

De plus, cela varie en fonction du type de format d'image. JPEG fonctionne principalement en essayant d'étaler la couleur autant que possible (dithering). C'est pourquoi les JPEG de qualité inférieure affichent des artefacts.PNG et GIF sont pour la plupart indexés, cependant, où la quantité globale de couleurs est tentée d'être réduite (bien que les deux peuvent également employer le dithering). Le PNG complique encore les choses en ce sens que vous pouvez également avoir des fichiers PNG sans perte, où toutes les couleurs et tous les pixels sont préservés mais une simple compression est appliquée (un peu comme une archive ZIP) pour réduire la taille du fichier. Tous auront un comportement différent les uns des autres et à diverses résolutions.

0

essayer de changer la qualité de InterpolationMode, SmoothingMode, CompositingQuality, PixelOffsetMode. Vous pouvez voir que tous ces paramètres sont réglés sur haute qualité