2016-02-03 5 views
6

Я хочу функцию, которая уменьшит размер изображения.Уменьшить размер изображения в C#

Функция должна отображать URL-адрес изображения, размер изображения равен 4 МБ или больше, и если он затем изменит размер на любовника, то 4 МБ и вернуть байты.

У меня есть следующий метод:

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

Но это не работает нормально.

У меня есть изображение в формате jpg в качестве примера.

Размер изображения немного больше, чем 4MB (4194587 bytes). Разрешение изображения 2272 x 1704.

Поэтому, когда я пытаюсь изменить размер изображения с помощью моего метода выше. Это первый вычислить «resizePercentage», как:

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

Но поскольку я поставил минимум resizePercent он будет установлен до 0,8 (80%).

resizePercent = 0.8; 

Тогда он рассчитает новую ширину и высоту с помощью этого resizePercent.

И новое разрешение будет: 1817 x 1363, а изображение будет изменено до нового разрешения. Но после сохранения в потоке и чтения байтов он возвращает еще большее изображение. Сайт возвращенного изображения «5146056 bytes» 5MB

У кого-нибудь есть идея, как реализовать это, или что-то не так, это мой метод, чтобы он возвращал большее изображение, даже разрешение уменьшено.

я должен быть в состоянии уменьшить размер изображений PNG, JPG и GIF

+0

Вы не знаете качество приложенного сжатия jpg при получении изображения. Возможно, вы сохраняете изображение с более высоким качеством (т. Е. Меньше сжатия), чем исходное изображение. Сохраняется ли проблема при работе с изображениями bmp? – wertzui

+0

Если ваше тестовое изображение является JPEG, возможно, оно было сжато с более высоким коэффициентом сжатия, чем по умолчанию использует .NET. Поскольку JPEG-файлы используют сжатие с потерями, существует широкий диапазон коэффициентов сжатия; они будут определять, как выглядит зернистое изображение. Для PNG, которые без потерь, все же возможно, что исходное изображение было сжато лучшим алгоритмом, чем то, что использует .NET. И так далее. – adv12

ответ

1

Там не 12:59 корреляции между размером файла изображения и разрешением, при работе со сжатыми растровыми изображениями. Эта корреляция существует для истинного растрового изображения (например, BMP), поскольку 1 пиксель всегда равен определенному количеству байтов (на основе цветового пространства).

Однако, когда речь идет о сжатых растровых изображениях, например JPEG, размер файла основывается на эффективности сжатия (сколько цветов необходимо кодировать в целом, сколько пикселей можно комбинировать на основе того же цвета или сколько сглаживание может быть сделано для создания большего количества пикселей одного цвета, которые можно комбинировать). Это может быть меньше с изображением с более низким разрешением, но оно также может оставаться неизменным или даже увеличиваться в зависимости от того, насколько эффективно исходное сжатие и как влияет меньшее количество пикселей на эффективность сжатия ,

Длинный и короткий, вы не можете просто применить простое сокращение разрешения на основе процентных ставок, чтобы обеспечить определенный размер файла. Лучшее, что вы могли бы сделать, постепенно уменьшает разрешение, проверяя размер файла с каждой итерацией, пока он не станет ниже вашего порога, если он действительно опустится ниже порога. С 4 МБ, чтобы играть, существует, по-видимому, определенная резолюция, которая определенно будет ниже этого, но там, где эта точка лежит, практически невозможно вычислить.

Кроме того, это зависит от типа изображения. JPEG работает в основном, пытаясь максимально распространять цвет (сглаживание). Вот почему изображения с низким качеством демонстрируют артефакты.PNG и GIF в основном индексируются, хотя, когда общее количество цветов пытается быть уменьшено (хотя оба могут также использовать сглаживание). PNG еще больше усложняет ситуацию, так как у вас также могут быть PNG без потерь, где сохраняются все цвета и пиксели, но для уменьшения размера файла применяется простое сжатие (подобно ZIP-архиву). Все они будут отличаться друг от друга и при различных разрешениях.

0

попытайтесь изменить качество InterpolationMode, SmoothingMode, CompositingQuality, PixelOffsetMode. Вы можете видеть, что все они настроены на высокое качество.

Смежные вопросы