Изменение размера изображения с помощью GDI + - PullRequest
1 голос
/ 08 января 2010

Я действительно пытаюсь добиться немного большей производительности из этого лакомого кусочка кода.Это не сильно используемый фрагмент кода, но используется каждый раз, когда загружается новое изображение, и 4 раза для каждого изображения (100px, 200px, 500px, 700px).Поэтому при обработке более 2 или 3 изображений он немного загружается на сервере.Также я пытаюсь выяснить, как заставить его правильно обрабатывать изображения с низким разрешением.В настоящее время это просто отрубает его на полпути, а не приятно.Примеры: Оригинал , большой , xLarge

public static byte[] ResizeImageFile(byte[] imageFile, int targetSize)
{
    using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))
    {
        Size newSize = CalculateDimensions(oldImage.Size, targetSize);

        using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppRgb))
        {
            newImage.SetResolution(oldImage.HorizontalResolution, oldImage.VerticalResolution);
            using (Graphics canvas = Graphics.FromImage(newImage))
            {
                canvas.SmoothingMode = SmoothingMode.AntiAlias;
                canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
                canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
                canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
                MemoryStream m = new MemoryStream();
                newImage.Save(m, ImageFormat.Jpeg);
                return m.GetBuffer();
            }
        }

    }
}

private static Size CalculateDimensions(Size oldSize, int targetSize)
{
    Size newSize = new Size();
    if (oldSize.Width > oldSize.Height)
    {
        newSize.Width = targetSize;
        newSize.Height = (int)(oldSize.Height * (float)targetSize / (float)oldSize.Width);
    }
    else
    {
        newSize.Width = (int)(oldSize.Width * (float)targetSize / (float)oldSize.Height);
        newSize.Height = targetSize;
    }
    return newSize;
}

Спасибо за помощь!

Ответы [ 3 ]

1 голос
/ 08 января 2010

(Threading - отличный совет.)

Попробуйте каждый раз вызывать метод с наименьшим возможным изображением в качестве входных данных вместо исходного изображения. Если исходное изображение, скажем, 2000px, создайте из него изображение 700px, а затем используйте только что созданное изображение 700px для создания 500px и т. Д.

С настройкой HighQualityBicubic я сомневаюсь, что вы заметите разницу в изображении размером 100px. (Но это конечно нужно проверять.)

1 голос
/ 16 декабря 2011

Для полноты, вот решение второй части вопроса, на которую так и не был дан ответ. При обработке изображения с низким разрешением изображение обрезалось. Решение сейчас кажется очевидным. Проблема заключается в этом фрагменте кода сверху:

using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, 
                                                    PixelFormat.Format32bppRgb))

Проблема в том, что я выбираю PixelFormat, не позволяя ему быть форматом исходного изображения. Правильный код здесь:

public static byte[] ResizeImageFile(byte[] imageFile, int targetSize)
{
    using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))
    {
        Size newSize = CalculateDimensions(oldImage.Size, targetSize);

    using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height,  
                                                        oldImage.PixelFormat))
    {
        newImage.SetResolution(oldImage.HorizontalResolution, 
                                                   oldImage.VerticalResolution);
        using (Graphics canvas = Graphics.FromImage(newImage))
        {
            canvas.SmoothingMode = SmoothingMode.AntiAlias;
            canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
            canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
            canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
            MemoryStream m = new MemoryStream();
            newImage.Save(m, ImageFormat.Jpeg);
            return m.GetBuffer();
        }
    }

   }
}
1 голос
/ 08 января 2010

Первая мысль, которая приходит в голову, вы думали о многопоточности? т.е. вызывать этот метод для каждого изображения (или серии изображений) в отдельном потоке? Таким образом, если на вашем сервере есть несколько ядер, вы сможете быстрее справиться с задачей. Просто мысль ...

...