Görüntü kalitesi etkilenmeden bir görüntüyü nasıl yeniden boyutlandırabilirim?
Görüntü kalitesi etkilenmeden bir görüntüyü nasıl yeniden boyutlandırabilirim?
Yanıtlar:
Gibi rcar diyor, bazı kalite kaybı olmadan, en iyi sizsiniz c # yapabilirim edemez:
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));
}
Vektör grafikleri yapmadığınız sürece, bir görüntü kalitesini potansiyel olarak kaybetmeden bir görüntüyü yeniden boyutlandırmanın bir yolu yoktur.
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;
}
Yapmak istediğiniz şeyin resimlerinizi "Yeniden Boyutlandırmak / Yeniden Örneklemek" olduğuna inanıyorum. İşte talimatlar veren ve bir yardımcı program sınıfı sağlayan iyi bir site (Benim de kullandığım):
http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
Yeniden boyutlandırmadığınız sürece bunu raster grafiklerle yapamazsınız.
İyi filtreleme ve yumuşatma ile yapabileceğiniz şey, göze çarpan herhangi bir kaliteyi kaybetmeden yeniden boyutlandırmaktır .
Ayrıca, görüntünün DPI meta verilerini (bazılarına sahip olduğunu varsayarak) değiştirebilir ve bu, tam olarak aynı piksel sayısını koruyacak, ancak görüntü editörlerinin 'gerçek dünya' ölçümlerinde onun hakkındaki düşüncelerini değiştirecektir.
Ve tüm temelleri kapsayacak şekilde, görüntünün gerçek boyutlarını değil de yalnızca dosya boyutunu kastettiyseniz, görüntü verilerinin kayıpsız kodlamasına bakmanızı öneririm. Bunun için önerim, resmi bir .png dosyası olarak yeniden kaydetmek olacaktır (boyayı pencerelerdeki resimler için ücretsiz bir kod dönüştürücü olarak kullanma eğilimindeyim. Resmi boyayla yükleyin, yeni formatta olduğu gibi kaydedin)
Piksel sayısını azalttığınız için bir görüntüyü kalite kaybı olmadan yeniden boyutlandıramazsınız.
İstemci tarafının boyutunu küçültmeyin, çünkü tarayıcılar resimleri yeniden boyutlandırma konusunda iyi bir iş çıkarmaz.
Yapabileceğiniz şey, boyutu işlemeden önce veya kullanıcı yüklerken programlı olarak değiştirmektir.
Bunu c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx ile yapmanın bir yolunu açıklayan bir makale burada.
Bu açık kaynaklı ASP.NET modülünün görüntü yeniden boyutlandırma kalitesini beğenip beğenmediğinize bakın . Canlı bir demo var, böylece onunla uğraşabilirsiniz. Photoshop çıktısından ayırt edilmesi (benim için) imkansız sonuçlar veriyor. Aynı zamanda benzer dosya boyutlarına sahiptir - MS, JPEG kodlayıcısında iyi bir iş çıkardı.
Orada bir şey var, bağlama duyarlı yeniden boyutlandırma, onu kullanıp kullanamayacağınızı bilmiyorum, ama bakmaya değer, orası kesin
Güzel bir video demosu (Büyütme ortaya doğru görünür) http://www.youtube.com/watch?v=vIFCV2spKtg
Burada bazı kodlar olabilir. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/
Bu aşırı mıydı? Belki pikselleri biraz bulanıklaştırmak için büyütülmüş bir görüntüye uygulayabileceğiniz bazı kolay filtreler vardır, buna bakabilirsiniz.
Daha büyük mü yoksa daha küçük mü yeniden boyutlandırıyorsunuz? Küçük bir yüzde ile mi yoksa 2x, 3x gibi daha büyük bir faktörle mi? Uygulamanız için kalite derken neyi kastediyorsunuz? Ve ne tür resimler - fotoğraflar, keskin kenarlı çizimler veya ne? Kendi düşük seviyeli piksel öğütme kodunuzu yazmak veya mevcut kitaplıklarla (.net veya her neyse) mümkün olduğunca çok yapmaya mı çalışıyorsunuz?
Bu konuda geniş bir bilgi birikimi var. Anahtar kavram enterpolasyondur.
Tarama önerileri:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* C # için: 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
* bu java'ya özeldir ancak eğitici olabilir - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
Burada, bu sınıfa filigran kodları da ekleyebilirsiniz:
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>();
}
}
Burada, bir C # resmi yeniden boyutlandırma kodu örneği sağlayan bir forum dizisi . C # ile yeniden örnekleme yapmak için GD kitaplık bağlayıcılarından birini kullanabilirsiniz .