Изменение размера изображения из базы данных SQL на лету с помощью MVC2

У меня есть простое приложение MVC2, которое загружает файл из браузера в базу данных MS SQL в виде большого двоичного объекта изображения.

Затем я могу вернуть результаты с чем-то вроде:

        public FileContentResult ShowPhoto(int id)
        {
           TemporaryImageUpload tempImageUpload = new TemporaryImageUpload();
           tempImageUpload = _service.GetImageData(id) ?? null;
           if (tempImageUpload != null)
           {
              byte[] byteArray = tempImageUpload.TempImageData;
              return new FileContentResult (temp, "image/jpeg");
           }
           return null;
        }

Но я хочу вернуть эти изображения с измененным размером как в виде миниатюр, так и в виде галереи. Возможно ли это сделать в рамках этого результата? Я играл с отличным imageresizer.net, но, похоже, он хочет хранить изображения на моем сервере, чего я хочу избежать. Можно ли это сделать на лету..?

Мне нужно сохранить исходный файл и, по возможности, не хранить изображения в виде файлов на сервере.

Спасибо за любые указатели!


person beebul    schedule 07.05.2012    source источник
comment
Ух ты! Оба ответа ниже работают блестяще. Я не знаю, что теперь делать с пометкой как отвеченный, так как я был бы на седьмом небе от счастья, если бы получил всего один из этих ответов :)   -  person beebul    schedule 07.05.2012


Ответы (3)


ImageResizer.NET позволяет передавать поток для изменения размера, см. использование управляемого API

Метод, который вы бы использовали:

ImageResizer.ImageBuilder.Current.Build(источник объекта, конечный объект, настройки ResizeSettings)

Я изменил ваш метод, чтобы сделать это таким образом, но он не проверен. Надеюсь, поможет.

public FileContentResult ShowPhoto(int id)
    {
       TemporaryImageUpload tempImageUpload = new TemporaryImageUpload();
       tempImageUpload = _service.GetImageData(id) ?? null;
       if (tempImageUpload != null)
       {
          byte[] byteArray = tempImageUpload.TempImageData;
          using(var outStream = new MemoryStream()){
              using(var inStream = new MemoryStream(byteArray)){
                  var settings = new ResizeSettings("maxwidth=200&maxheight=200");
                  ImageResizer.ImageBuilder.Current.Build(inStream, outStream, settings);
                  var outBytes = outStream.ToArray();
                  return new FileContentResult (outBytes, "image/jpeg");
              }
          }
       }
       return null;
    }
person w.brian    schedule 07.05.2012
comment
Я выбираю это как ответ, потому что я уже использовал ImageResizer. Спасибо! - person beebul; 07.05.2012
comment
На самом деле «inStream» не требуется, ImageResizer может напрямую использовать массив byte[]. Кроме того, если вы не хотите кэшировать диск для определенных запросов, вы можете добавить &cache=no вместо получения менее эффективного результата MVC... - person Lilith River; 10.07.2012
comment
@ComputerLinguist, похоже, этот метод не использует DiskCaching. Есть ли где-нибудь пример, который показывает преобразование массива байтов выше, но с использованием кэширования диска? - person vernak2539; 02.12.2014

Недавно был подкаст Hanselminutes на Изменение размера изображения, в котором Натанаэль Джонс обсуждал некоторые подводные камни изменения размера изображения.

Даже если у вас нет 30 с лишним минут, чтобы прослушать полный подкаст, примечания к шоу указывают на некоторые интересные подводные камни изменения размера, а также библиотека для изменения размера изображения, также написанная Натанаэлем Джонсом.

person Jack Bolding    schedule 07.05.2012
comment
Спасибо, Джек, я обязательно это проверю. - person beebul; 07.05.2012

Вы можете изменить размер изображения на лету:

public void ResizeImage(Stream input, Stream output, int newWidth, int maxHeight)
{
    using (var srcImage = Image.FromStream(input))
    {
        int newHeight = srcImage.Height * newWidth / srcImage.Width;
        if (newHeight > maxHeight)
        {
            newWidth = srcImage.Width * maxHeight / srcImage.Height;
            newHeight = maxHeight;
        }

        using (var newImage = new Bitmap(newWidth, newHeight))
        using (var gr = Graphics.FromImage(newImage))
        {
            gr.SmoothingMode = SmoothingMode.AntiAlias;
            gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
            gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
            gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
            newImage.Save(output, ImageFormat.Jpeg);
        }
    }
}

и тогда у вас может быть 2 действия контроллера (одно, которое отображает полный размер изображения, а другое — миниатюру):

public ActionResult Thumbnail(int id)
{
    var tempImageUpload = new TemporaryImageUpload();
    tempImageUpload = _service.GetImageData(id) ?? null;
    if (tempImageUpload == null)
    {
        return HttpNotFound();
    }

    using (var input = new MemoryStream(tempImageUpload.TempImageData))
    using (var output = new MemoryStream())
    {
        ResizeImage(input, output, 640, 1000);
        return File(output.ToArray(), "image/jpeg");
    }
}
person Darin Dimitrov    schedule 07.05.2012
comment
Спасибо Дарин, это было полезно :) Дэвид - person beebul; 07.05.2012