Изменение размеров изображения в asp.net, не теряя качество изображения

Я разрабатываю ASP.NET 3,5 веб-приложения, в которых я позволяю моим пользователям загружать или jpeg, gif, bmp или изображения png. Если размеры загруженного изображения больше затем 103 x 32, я хочет изменить размер загруженного изображения к 103 x 32. Я считал некоторые сообщения в блоге и статьи, и также попробовал некоторые примеры кода, но ничто, кажется, не работает правильно. Кто-либо сделал, преуспевают в том, чтобы делать это?

35
задан Juha Syrjälä 8 May 2010 в 10:41
поделиться

4 ответа

Некоторое время назад у меня была такая же проблема, и я решил ее следующим образом:

private Image RezizeImage(Image img, int maxWidth, int maxHeight)
{
    if(img.Height < maxHeight && img.Width < maxWidth) return img;
    using (img)
    {
        Double xRatio = (double)img.Width / maxWidth;
        Double yRatio = (double)img.Height / maxHeight;
        Double ratio = Math.Max(xRatio, yRatio);
        int nnx = (int)Math.Floor(img.Width / ratio);
        int nny = (int)Math.Floor(img.Height / ratio);
        Bitmap cpy = new Bitmap(nnx, nny, PixelFormat.Format32bppArgb);
        using (Graphics gr = Graphics.FromImage(cpy))
        {
            gr.Clear(Color.Transparent);

            // This is said to give best quality when resizing images
            gr.InterpolationMode = InterpolationMode.HighQualityBicubic;

            gr.DrawImage(img,
                new Rectangle(0, 0, nnx, nny),
                new Rectangle(0, 0, img.Width, img.Height),
                GraphicsUnit.Pixel);
        }
        return cpy;
    }

}

private MemoryStream BytearrayToStream(byte[] arr)
{
    return new MemoryStream(arr, 0, arr.Length);
}

private void HandleImageUpload(byte[] binaryImage)
{
    Image img = RezizeImage(Image.FromStream(BytearrayToStream(binaryImage)), 103, 32);
    img.Save("IMAGELOCATION.png", System.Drawing.Imaging.ImageFormat.Gif);
}

Я только что прочитал, что это был способ получить наивысшее качество.

35
ответ дан 27 November 2019 в 06:50
поделиться

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

-121--3397699-

Вы можете считать это недопустимым взломом, но это сработало в MP3 плеере, который я написал. Требуется небольшое дополнение кода к одному из классов JLayer.

Добавьте следующий метод в javazoom.jl.player.JavaSoundAudioDevice.

public void setLineGain(float gain)
{
    if (source != null)
    {
        FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
        float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());

        volControl.setValue(newGain);
    }
}

Этот новый метод позволяет изменить громкость с помощью кода, подобного этому.

if (audio instanceof JavaSoundAudioDevice)
{
    JavaSoundAudioDevice jsAudio = (JavaSoundAudioDevice) audio;
    jsAudio.setLineGain(yourGainGoesHere);
}
-121--4246277-

Это код, который я использую. Он поддерживает поворот, а также устанавливает разрешение изображения в соответствии со стандартами JPEG 72dpi @ 24-битный цвет (по умолчанию GDI + сохраняет изображения в 96dpi @ 32-битный цвет). Он также устраняет проблему с черной/серой границей, с которой сталкиваются некоторые люди при изменении размеров изображений.

/// <summary>
/// Resizes and rotates an image, keeping the original aspect ratio. Does not dispose the original
/// Image instance.
/// </summary>
/// <param name="image">Image instance</param>
/// <param name="width">desired width</param>
/// <param name="height">desired height</param>
/// <param name="rotateFlipType">desired RotateFlipType</param>
/// <returns>new resized/rotated Image instance</returns>
public static Image Resize(Image image, int width, int height, RotateFlipType rotateFlipType)
{
    // clone the Image instance, since we don't want to resize the original Image instance
    var rotatedImage = image.Clone() as Image;
    rotatedImage.RotateFlip(rotateFlipType);
    var newSize = CalculateResizedDimensions(rotatedImage, width, height);

    var resizedImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppArgb);
    resizedImage.SetResolution(72, 72);

    using (var graphics = Graphics.FromImage(resizedImage))
    {
        // set parameters to create a high-quality thumbnail
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.AntiAlias;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        // use an image attribute in order to remove the black/gray border around image after resize
        // (most obvious on white images), see this post for more information:
        // http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
        using (var attribute = new ImageAttributes())
        {
            attribute.SetWrapMode(WrapMode.TileFlipXY);

            // draws the resized image to the bitmap
            graphics.DrawImage(rotatedImage, new Rectangle(new Point(0, 0), newSize), 0, 0, rotatedImage.Width, rotatedImage.Height, GraphicsUnit.Pixel, attribute);
        }
    }

    return resizedImage;
}

/// <summary>
/// Calculates resized dimensions for an image, preserving the aspect ratio.
/// </summary>
/// <param name="image">Image instance</param>
/// <param name="desiredWidth">desired width</param>
/// <param name="desiredHeight">desired height</param>
/// <returns>Size instance with the resized dimensions</returns>
private static Size CalculateResizedDimensions(Image image, int desiredWidth, int desiredHeight)
{
    var widthScale = (double)desiredWidth / image.Width;
    var heightScale = (double)desiredHeight / image.Height;

    // scale to whichever ratio is smaller, this works for both scaling up and scaling down
    var scale = widthScale < heightScale ? widthScale : heightScale;

    return new Size
                   {
                       Width = (int) (scale * image.Width),
                       Height = (int) (scale * image.Height)
                   };
}
41
ответ дан 27 November 2019 в 06:50
поделиться

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

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

Вот что я сделал.

   private Image getImageFromBytes(byte[] myByteArray)
    {                        
        System.IO.MemoryStream newImageStream = new System.IO.MemoryStream(myByteArray, 0, myByteArray.Length);
        Image image = Image.FromStream(newImageStream, true);
        Bitmap resized = new Bitmap(image, image.Width / 2, image.Height / 2);
        image.Dispose();
        newImageStream.Dispose();
        return resized;
    }
0
ответ дан 27 November 2019 в 06:50
поделиться

Код, связанный с фактическим изменением размера растрового изображения, выглядит следующим образом.

public static Bitmap ResizeBitmap( Bitmap originalBitmap, int requiredHeight, int requiredWidth )
{
   int[] heightWidthRequiredDimensions;

   // Pass dimensions to worker method depending on image type required
   heightWidthRequiredDimensions = WorkDimensions(originalBitmap.Height, originalBitmap.Width, requiredHeight, requiredWidth);


   Bitmap resizedBitmap = new Bitmap( heightWidthRequiredDimensions[1],
                                      heightWidthRequiredDimensions[0] );

   const float resolution = 72;

   resizedBitmap.SetResolution( resolution, resolution );

   Graphics graphic = Graphics.FromImage( (Image) resizedBitmap );

   graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
   graphic.DrawImage( originalBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height );

   graphic.Dispose();
   originalBitmap.Dispose();
   //resizedBitmap.Dispose(); // Still in use


   return resizedBitmap;
}


private static int[] WorkDimensions(int originalHeight, int originalWidth, int requiredHeight, int requiredWidth )
{
   int imgHeight = 0;
   int imgWidth = 0;

   imgWidth = requiredHeight;
   imgHeight = requiredWidth;


   int requiredHeightLocal = originalHeight;
   int requiredWidthLocal = originalWidth;

   double ratio = 0;

   // Check height first
   // If original height exceeds maximum, get new height and work ratio.
   if ( originalHeight > imgHeight )
   {
       ratio = double.Parse( ( (double) imgHeight / (double) originalHeight ).ToString() );
       requiredHeightLocal = imgHeight;
       requiredWidthLocal = (int) ( (decimal) originalWidth * (decimal) ratio );
   }

   // Check width second. It will most likely have been sized down enough
   // in the previous if statement. If not, change both dimensions here by width.
   // If new width exceeds maximum, get new width and height ratio.
   if ( requiredWidthLocal >= imgWidth )
   {
       ratio = double.Parse( ( (double) imgWidth / (double) originalWidth ).ToString() );
       requiredWidthLocal = imgWidth;
       requiredHeightLocal = (int) ( (double) originalHeight * (double) ratio );
   }

   int[] heightWidthDimensionArr = { requiredHeightLocal, requiredWidthLocal };

   return heightWidthDimensionArr;
}
}

Эта запись в блоге содержит полный исходный код для изменения размера изображения и сжатия (если требуется)

http://blog.bombdefused.com/2010/08/bulk-image-optimizer-in-c-full-source.html

2
ответ дан 27 November 2019 в 06:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: