2010-02-23 2 views
33

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

+1

Post код, который вы используете, что не работает, и объяснить, каким образом это не работает. – RedFilter

+1

Вы хотите заставить 103x32? Или лучше всего подходит? – citronas

+0

'ImageBuilder.Current.Build (файл HttpPostedFile, строковый путь, новый ResizeSettings (" width = 103 & height = 32 ")); // Использование библиотеки [Image Resizer library] (http://imageresizing.net) –

ответ

30

У меня была та же проблема, некоторое время назад и имел дело с ним так:

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); 
} 

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

+0

+1 Nice : "Double ratio = Math.Max ​​(xRatio, yRatio);" – Joop

+0

В новой версии я также принимаю во внимание, что я не буду растягивать изображения, но это должно быть довольно легко выработать: -P (hint: 'ration = Math.Min (ration, 1.0);') – Alxandr

+0

Well , есть [несколько дополнительных настроек, которые помогут] (http://nathanaeljones.com/163/20-image-resizing-pitfalls/), например смещение пикселей. –

0

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

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

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

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; 
    } 
41

Это код, который я использую. Он поддерживает вращение, а также устанавливает разрешение изображения в соответствии со стандартами JPEG с разрешением 72dpi @ 24-bit (по умолчанию 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) 
        }; 
} 
+3

Благодарим за решение проблемы с серой границей. –

+0

Как и выше, спасибо за исправление проблемы с границей. –

+0

Это решение изменяет размер без изменений исходных цветов изображения! Отличная работа! – danyolgiax

2

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

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