Come posso ridimensionare un'immagine senza che la qualità dell'immagine venga modificata?
Come posso ridimensionare un'immagine senza che la qualità dell'immagine venga modificata?
Risposte:
Come dice rcar , non puoi senza perdere un po 'di qualità, il meglio che puoi fare in c # è:
Bitmap newImage = new Bitmap(newWidth, newHeight);
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
}
A meno che tu non stia facendo grafica vettoriale, non c'è modo di ridimensionare un'immagine senza potenzialmente perdere un po 'di qualità dell'immagine.
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
Credo che quello che stai cercando di fare sia "Ridimensionare / Ricampionare" le tue immagini. Ecco un buon sito che fornisce istruzioni e fornisce una classe di utilità (che anche io uso):
http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
A meno che non si ridimensiona, non è possibile farlo con la grafica raster.
Quello che puoi fare con un buon filtraggio e levigatura è ridimensionare senza perdere alcuna qualità evidente .
Puoi anche modificare i metadati DPI dell'immagine (supponendo che ne abbia alcuni) che manterranno esattamente lo stesso numero di pixel, ma cambieranno il modo in cui gli editor di immagini la pensano nelle misurazioni del "mondo reale".
E solo per coprire tutte le basi, se intendi davvero solo la dimensione del file dell'immagine e non le dimensioni effettive dell'immagine, ti suggerisco di guardare una codifica senza perdite dei dati dell'immagine. Il mio suggerimento per questo sarebbe salvare nuovamente l'immagine come file .png (tendo a usare paint come transcodificatore gratuito per le immagini in Windows. Carica l'immagine in Paint, salva come nel nuovo formato)
Non puoi ridimensionare un'immagine senza perdere un po 'di qualità, semplicemente perché stai riducendo il numero di pixel.
Non ridurre le dimensioni lato client, perché i browser non fanno un buon lavoro di ridimensionamento delle immagini.
Quello che puoi fare è modificare programmaticamente le dimensioni prima di renderlo o come un utente lo carica.
Ecco un articolo che spiega un modo per farlo in c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx
Vedi se ti piace la qualità di ridimensionamento dell'immagine di questo modulo ASP.NET open source. C'è una demo dal vivo, quindi puoi giocarci da solo. Produce risultati che sono (per me) impossibili da distinguere dall'output di Photoshop. Ha anche dimensioni di file simili: MS ha fatto un buon lavoro con il suo codificatore JPEG.
C'è qualcosa là fuori, ridimensionamento consapevole del contesto, non so se sarai in grado di usarlo, ma vale la pena guardarlo, questo è certo
Un bel video dimostrativo (l'ingrandimento appare verso il centro) http://www.youtube.com/watch?v=vIFCV2spKtg
Qui potrebbe esserci del codice. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/
È stato eccessivo? Forse ci sono alcuni semplici filtri che puoi applicare a un'immagine ingrandita per sfocare un po 'i pixel, potresti esaminarli.
Stai ridimensionando più grande o più piccolo? Di una piccola% o di un fattore maggiore come 2x, 3x? Cosa intendi per qualità per la tua applicazione? E che tipo di immagini: fotografie, disegni al tratto netti o cosa? Stai scrivendo il tuo codice di macinazione pixel di basso livello o cercando di farlo il più possibile con le librerie esistenti (.net o altro)?
C'è un ampio corpo di conoscenza su questo argomento. Il concetto chiave è l'interpolazione.
Suggerimenti per la navigazione:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* per C #: https: //secure.codeproject.com/KB/GDI-plus/imageprocessing4.aspx?display=PrintAll&fid=3657&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=629945
* questo è specifico per Java ma potrebbe essere educativo - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
Qui puoi trovare anche aggiungere codici di filigrana in questa classe:
public class ImageProcessor
{
public Bitmap Resize(Bitmap image, int newWidth, int newHeight, string message)
{
try
{
Bitmap newImage = new Bitmap(newWidth, Calculations(image.Width, image.Height, newWidth));
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(image, new Rectangle(0, 0, newImage.Width, newImage.Height));
var myBrush = new SolidBrush(Color.FromArgb(70, 205, 205, 205));
double diagonal = Math.Sqrt(newImage.Width * newImage.Width + newImage.Height * newImage.Height);
Rectangle containerBox = new Rectangle();
containerBox.X = (int)(diagonal / 10);
float messageLength = (float)(diagonal / message.Length * 1);
containerBox.Y = -(int)(messageLength / 1.6);
Font stringFont = new Font("verdana", messageLength);
StringFormat sf = new StringFormat();
float slope = (float)(Math.Atan2(newImage.Height, newImage.Width) * 180 / Math.PI);
gr.RotateTransform(slope);
gr.DrawString(message, stringFont, myBrush, containerBox, sf);
return newImage;
}
}
catch (Exception exc)
{
throw exc;
}
}
public int Calculations(decimal w1, decimal h1, int newWidth)
{
decimal height = 0;
decimal ratio = 0;
if (newWidth < w1)
{
ratio = w1 / newWidth;
height = h1 / ratio;
return height.To<int>();
}
if (w1 < newWidth)
{
ratio = newWidth / w1;
height = h1 * ratio;
return height.To<int>();
}
return height.To<int>();
}
}
Ecco un thread del forum che fornisce un esempio di codice di ridimensionamento dell'immagine C #. È possibile utilizzare uno dei raccoglitori della libreria GD per eseguire il ricampionamento in C #.