Изменение размера изображения без потери качества
Мне нужно изменить размер изображения, но это не может повлиять на качество изображения.
11 ответов
Как говорит rcar, вы не можете без потери качества, лучшее, что вы можете сделать в 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));
}
Если вы не занимаетесь векторной графикой, нет способа изменить размер изображения без потери качества изображения.
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;
}
отсюда
Я считаю, что вы хотите "изменить размер / изменить размер" ваших изображений. Вот хороший сайт, который дает инструкции и предоставляет служебный класс (который я также использую):
http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
Если вы не измените размер, вы не сможете сделать это с растровой графикой.
Что вы можете сделать с хорошей фильтрацией и сглаживанием, так это изменить размер без потери заметного качества.
Вы также можете изменить метаданные DPI изображения (при условии, что у них их есть), которые сохранят точно такое же количество пикселей, но изменит то, как редакторы изображений думают об этом в измерениях "реального мира".
И просто для того, чтобы охватить все основы, если вы действительно имели в виду только размер файла изображения, а не фактические размеры изображения, я предлагаю вам взглянуть на кодирование данных изображения без потерь. Мое предложение для этого было бы сохранить изображение в виде файла.png (я, как правило, использую краску в качестве бесплатного транскодера для изображений в окнах. Загружайте изображение в краске, сохраняйте как в новом формате)
Вы не можете изменить размер изображения без потери качества просто потому, что уменьшаете количество пикселей.
Не уменьшайте размер клиентской части, потому что браузеры плохо справляются с изменением размера изображений.
Что вы можете сделать, так это программно изменить размер перед его рендерингом или по мере его загрузки пользователем.
Вот статья, которая объясняет один из способов сделать это в C#: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx
Посмотрите, нравится ли вам качество изменения размера этого модуля ASP.NET с открытым исходным кодом. Есть живая демонстрация, так что вы можете возиться с ней самостоятельно. Это дает результаты, которые (для меня) невозможно отличить от результатов Photoshop. У этого также есть подобные размеры файла - MS сделала хорошую работу на их кодере JPEG.
Здесь вы можете найти также добавить коды водяных знаков в этом классе:
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>();
}
}
Вы изменяете размер больше или меньше? На небольшой процент или на больший коэффициент, такой как 2x, 3x? Что вы подразумеваете под качеством для вашего приложения? А какой тип изображений - фотографии, жесткие штриховые рисунки или что? Написание собственного низкоуровневого пиксельного шлифовального кода или попытки сделать это как можно больше с существующими библиотеками (.net или что-то еще)?
На эту тему есть большой объем знаний. Ключевой концепцией является интерполяция.
Рекомендации по просмотру:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* для 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* это специфично для java может быть образовательным - http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
Есть что-то, изменение контекста с учетом контекста, не знаю, сможете ли вы его использовать, но на это стоит посмотреть, это точно
Хорошая демонстрация видео (увеличение появляется в середине) http://www.youtube.com/watch?v=vIFCV2spKtg
Здесь может быть какой-то код. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/
Это было излишним? Возможно, есть несколько простых фильтров, которые вы можете применить к увеличенному изображению, чтобы немного размыть пиксели, вы можете посмотреть на это.
Вот ветка форума, которая предоставляет пример кода изменения размера изображения на C#. Вы можете использовать одну из библиотек GD для повторной выборки в C#.