2016-02-03 21 views
6

Desidero una funzione che riduca le dimensioni dell'immagine.Ridurre le dimensioni dell'immagine in C#

La funzione dovrebbe richiedere l'URL dell'immagine, controllare l'immagine 4MB o più grande e se è quindi ridimensionarla ad un amatore allora 4MB e restituire i byte.

devo metodo successivo:

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

Ma questo non funziona bene.

Ho un'immagine jpg come esempio.

La dimensione dell'immagine è leggermente superiore a 4 MB (4194587 byte). Risoluzione dell'immagine è 2272 x 1704.

Così quando provo a ridimensionare questa immagine con il mio metodo sopra. E prima calcolare "resizePercentage" come:

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

Anzi, perché vi ho posto minimo di resizePercent sarà impostato a 0.8 (80%).

resizePercent = 0.8; 

Quindi calcola nuova larghezza e altezza con questo resizePercent.

E la nuova risoluzione sarà: 1817 x 1363 e l'immagine verrà ridimensionata a nuova risoluzione. Ma dopo essere stato salvato nello stream e letto byte, restituisce un'immagine ancora più grande. Il sito dell'immagine restituita è "5146056 byte" 5MB

Così chiunque ha idea di come implementarlo, o cosa non va in questo mio metodo in modo che restituisca un'immagine più grande, anche la risoluzione è ridotta.

dovrei essere in grado di ridurre le dimensioni delle immagini PNG, JPG e GIF

+0

Non si conosce la qualità della compressione jpg applicata quando si riceve l'immagine. Quindi forse stai salvando l'immagine con una qualità più alta (cioè meno compressione) rispetto all'immagine originale. Il problema persiste quando lavori con immagini bmp? – wertzui

+0

Se l'immagine di prova è un JPEG, probabilmente è stata compressa con un rapporto di compressione più alto di quanto .NET usi per impostazione predefinita. Poiché i JPEG utilizzano la compressione con perdita, è disponibile un'ampia gamma di rapporti di compressione; determineranno quanto appare sgranata l'immagine risultante. Per i PNG, che sono senza perdita di dati, è comunque possibile che l'immagine originale sia stata compressa da un algoritmo migliore di quello utilizzato da .NET. E così via. – adv12

risposta

1

Non c'è un 1-1 correlazione tra le dimensioni e la risoluzione del file immagine, quando si tratta di bitmap compresse. Tale correlazione esiste per una bitmap vera (ad esempio BMP), poiché 1 pixel è sempre uguale a un numero definito di byte (basato sullo spazio colore).

Tuttavia, quando si parla di bitmap compressi, come JPEG, la dimensione del file si basa sull'efficienza della compressione (quanti colori devono essere codificati nel loro insieme, quanti pixel possono combinarsi in base allo stesso colore o quanto il dithering può essere fatto per creare più pixel dello stesso colore che possono essere combinati). Questo potrebbe finire per essere meno con un'immagine a bassa risoluzione, ma potrebbe anche facilmente rimanere invariato o addirittura aumentare, a seconda dell'efficienza della compressione originale e di quale effetto ha una minore quantità di pixel sull'efficienza della compressione .

Lungo e breve, non è possibile applicare una semplice riduzione in percentuale basata sulla risoluzione per garantire una certa dimensione del file. Il meglio che si può realmente fare è diminuire gradualmente la risoluzione, testando le dimensioni del file a ogni iterazione, fino a quando non è al di sotto della soglia, assumendo che vada effettivamente sotto la soglia. Con 4 MB con cui giocare, è ipotizzabile una certa risoluzione che sarebbe sicuramente inferiore a quella, ma dove quel punto giace è praticamente impossibile da calcolare.

Inoltre, questo può variare in base al tipo di formato dell'immagine. Il JPEG funziona principalmente cercando di diffondere il colore il più possibile (dithering). Questo è il motivo per cui i file JPEG di qualità inferiore mostrano artefatti.PNG e GIF sono per lo più indicizzati, tuttavia, dove si tenta di ridurre la quantità complessiva di colori (sebbene entrambi possano utilizzare anche il dithering). Il PNG complica ulteriormente la questione in quanto è possibile avere anche PNG senza perdita di dati, in cui vengono conservati tutti i colori e i pixel, ma viene applicata una semplice compressione (simile a un archivio ZIP) per ridurre le dimensioni del file. Tutti questi avranno un comportamento diverso l'uno dall'altro e a varie risoluzioni.

0

provare a modificare la qualità di InterpolationMode, SmoothingMode, CompositingQuality, PixelOffsetMode. È possibile vedere che tutti questi sono impostati su alta qualità

Problemi correlati