Рендеринг минимально возможного размера изображения с помощью библиотеки MVC3 vs Webforms - PullRequest
1 голос
/ 21 июля 2011

Я в процессе переноса приложения webforms на MVC3. По иронии судьбы, все это классные бины, кроме одного - изображения поступают из обработчика, в частности из Microsoft Generated Image Handler . Это работает очень хорошо - в среднем фотография 450 КБ выводится примерно с 20 КБ.

Фактическая фотография на диске весит 417 КБ, поэтому я получаю большое сокращение.

Переходя к MVC3, я хотел бы отбросить обработчик и использовать действие контроллера. Однако я, кажется, не могу добиться такого же уменьшения размера файла при рендеринге изображения. Я прошелся по источнику и взял точную копию кода преобразования изображения , но я только добился 230 ~ kb, что все еще намного больше, чем выводит обработчик ms - 16 kb.

Вы можете увидеть пример как контроллера, так и обработчика здесь

Я прошелся по исходному коду обработчика и не вижу ничего, что сжимает изображение дальше. Если вы посмотрите на оба изображения, вы увидите разницу: изображение, обработанное обработчиком, менее четкое, более зернистое, но все же то, что я считаю удовлетворительным для моих нужд.

Кто-нибудь может дать мне какие-нибудь указатели здесь? используется ли выходное сжатие? или я упускаю что-то очень очевидное?

Приведенный ниже код используется в моем домашнем контроллере для визуализации изображения и является точной копией метода FitImage в классе преобразования изображения , который использует обработчик ...

public ActionResult MvcImage()
    {
        var file = Server.MapPath("~/Content/test.jpg");
        var img = System.Drawing.Image.FromFile(file);
        var sizedImg = MsScale(img);

        var newFile = Server.MapPath("~/App_Data/test.jpg");
        if (System.IO.File.Exists(newFile))
        {
            System.IO.File.Delete(newFile);
        }
        sizedImg.Save(newFile);
        return File(newFile, "image/jpeg");
    }

private Image MsScale(Image img)
    {
        var scaled_height = 267;
        var scaled_width = 400;
        int resizeWidth = 400;
        int resizeHeight = 267;
        if (img.Height == 0)
        {
            resizeWidth = img.Width;
            resizeHeight = scaled_height;
        }
        else if (img.Width == 0)
        {
            resizeWidth = scaled_width;
            resizeHeight = img.Height;
        }
        else
        {
            if (((float)img.Width / (float)img.Width < img.Height / (float)img.Height))
            {
                resizeWidth = img.Width;
                resizeHeight = scaled_height;
            }
            else
            {
                resizeWidth = scaled_width;
                resizeHeight = img.Height;
            }
        }

        Bitmap newimage = new Bitmap(resizeWidth, resizeHeight);
        Graphics gra = Graphics.FromImage(newimage);
        SetupGraphics(gra);
        gra.DrawImage(img, 0, 0, resizeWidth, resizeHeight);
        return newimage;
    }

    private void SetupGraphics(Graphics graphics)
    {
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighSpeed;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighSpeed;
    }

Ответы [ 2 ]

1 голос
/ 28 июля 2011

Я полагаю, что по умолчанию это формат PNG, хотя решение Tridus также решает эту проблему.

Тем не менее, я настоятельно рекомендую использовать эту MVC-дружественную библиотеку вместо , поскольку она исключает всех ошибок при изменении размера изображения и не приводит к утечке памяти. Это очень легкий, бесплатный и полностью поддерживаемый.

1 голос
/ 21 июля 2011

Если вы не установили качество на кодере, он по умолчанию использует 100.Вы никогда не добьетесь хорошего уменьшения размера при использовании 100 из-за способа работы таких форматов изображений, как JPEG.У меня есть пример кода VB.net о том, как установить параметр качества, который вы сможете адаптировать.

80L, вот настройка качества.80 по-прежнему дает вам довольно высокое качество изображения, но при уменьшении размера DRASTIC более 100.

            Dim graphic As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(newImage)
            graphic.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
            graphic.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality
            graphic.PixelOffsetMode = Drawing.Drawing2D.PixelOffsetMode.HighQuality
            graphic.CompositingQuality = Drawing.Drawing2D.CompositingQuality.HighQuality
            graphic.DrawImage(sourceImage, 0, 0, width, height)

            ' now encode and send the new image
            ' This is the important part

            Dim info() As Drawing.Imaging.ImageCodecInfo = Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
            Dim encoderParameters As New Drawing.Imaging.EncoderParameters(1)

            encoderParameters.Param(0) = New Drawing.Imaging.EncoderParameter(Drawing.Imaging.Encoder.Quality, 80L)
            ms = New System.IO.MemoryStream
            newImage.Save(ms, info(1), encoderParameters)

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

...