Как уменьшить размер изображения (в КБ) при загрузке и масштабировании? - PullRequest
0 голосов
/ 20 ноября 2018

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

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

Это моя функция:

    public Image ScaleProportionally(Image imgPhoto, int shortestEdge = 0)
    {
        float sourceWidth = imgPhoto.Width;
        float sourceHeight = imgPhoto.Height;
        float destHeight = 0;
        float destWidth = 0;
        int sourceX = 0;
        int sourceY = 0;
        int destX = 0;
        int destY = 0;

        if (shortestEdge > 0)
        {
            if(sourceWidth < sourceHeight)
            {
                destWidth = shortestEdge;
                destHeight = (float)(sourceHeight * shortestEdge / sourceWidth);
            }
            else
            {
                destWidth = (float)(shortestEdge * sourceWidth) / sourceHeight;
                destHeight = shortestEdge;
            }

            Bitmap bmPhoto = new Bitmap((int)destWidth, (int)destHeight,
                                        PixelFormat.Format32bppPArgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode = InterpolationMode.Low;
            grPhoto.CompositingQuality = CompositingQuality.AssumeLinear;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, (int)destWidth, (int)destHeight),
                new Rectangle(sourceX, sourceY, (int)sourceWidth, (int)sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();

        return bmPhoto;

        }
        else
        {

            return imgPhoto;
        }
    }

У меня изначально было это ниже для InterpolationMode и CompositingQuality, но изменение их, как указано выше, на самом деле не уменьшило размер масштабированной фотографии:

            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
            grPhoto.CompositingQuality = CompositingQuality.HighSpeed;

Исходное изображение имеет 546 КБ, а масштабированное - 1 МБ, почти вдвое больше.

Как уменьшить размер при масштабировании?

Я использую .NET 4.5

РЕДАКТИРОВАТЬ

Функция сохранения файла:

    public int CreateAndSaveMedia(HttpPostedFileBase file, string fileName, string mediaType, string caption, int folderId, Dictionary<string,string> additionalProperties = null)
    {
        // Create temp mediaitem folder
        string mediaDirectory = System.Web.HttpContext.Current.Server.MapPath($"~/media/");
        var path = Path.Combine(mediaDirectory, fileName);
        file.SaveAs(path);

        Image imgOriginal = Image.FromFile(path);

        //pass in whatever value you want
        Image imgActual = _imageService.ScaleProportionally(imgOriginal, 450);
        imgOriginal.Dispose();
        imgActual.Save(path);
        imgActual.Dispose();

        // Open file and assign media url to media content
        FileStream s = new FileStream(path, FileMode.Open);

        // Save media content
        IMedia media = _mediaService.CreateMedia(caption, folderId, mediaType);
        _mediaService.Save(media);
        media.SetValue("umbracoFile", Path.GetFileName(path), s);

        if (additionalProperties != null)
        {
            foreach (var itm in additionalProperties)
            {
                media.SetValue(itm.Key, itm.Value);
            }
        }

        _mediaService.Save(media);

        // Get media Id
        int mediaId = media.Id;

        s.Close();
        System.IO.File.Delete(path);

        return mediaId;
    }

РЕДАКТИРОВАТЬ

После комментария @ Nyerguds я специально установил новыйТип изображения в JPG, и это имеет значение:

imgActual.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);

Спасибо!

1 Ответ

0 голосов
/ 20 ноября 2018

Вы не устанавливаете тип при сохранении, что делает Image.Save по умолчанию либо для обнаруженного типа исходного изображения, либо для PNG, если оно не может быть сохранено в точном формате, обнаруженном на входе.

Сжатие, которое вы получаете из png, во многом зависит от того, что находится на изображении;png не очень хорошо сжимает сложные изображения, такие как фотографии, и изменение его размера до меньшего может на самом деле увеличить сложность.Кроме того, алгоритмы сжатия PNG .Net Framework не так хороши, как в реальных программах манипуляции с графикой.

Для уменьшения размера, вы можете специально повторно сохранить в формате JPEG.

Этоможет быть сделано двумя способами.Простой способ - просто указать Jpeg в качестве типа сохранения:

imgActual.Save(path, ImageFormat.Jpeg);

Более продвинутый метод - использовать кодировщик JPEG.Если вы сделаете это, вы можете установить качество сохранения (в действительности, обратно пропорциональное степени сжатия) изображения в процентах (значения от 1 до 100).К сожалению, не существует простого способа получить его;вам нужно получить его по GUID, просмотрев полный список доступных кодеров:

Int32 quality = 80;
ImageCodecInfo jpegEncoder = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == ImageFormat.Jpeg.Guid);
EncoderParameters encparams = new EncoderParameters(1);
encparams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
imgActual.Save(path, jpegEncoder, encparams);
...