代码之家  ›  专栏  ›  技术社区  ›  Tim Meers

使用gdi调整图像大小+

  •  1
  • Tim Meers  · 技术社区  · 15 年前

    我真的想从这段代码中找出更多的性能。它不是一个很常用的代码位,但每次上载新图像时都会用到,每个图像4次(100px、200px、500px、700px)。所以当有超过2或3个的图像处理时,服务器会变得有点忙。另外,我还想知道如何让它以低分辨率正确处理图像。目前,它只是把它砍掉一半,而不是全部。 实例: Original , large , xLarge

    public static byte[] ResizeImageFile(byte[] imageFile, int targetSize)
    {
        using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))
        {
            Size newSize = CalculateDimensions(oldImage.Size, targetSize);
    
            using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppRgb))
            {
                newImage.SetResolution(oldImage.HorizontalResolution, oldImage.VerticalResolution);
                using (Graphics canvas = Graphics.FromImage(newImage))
                {
                    canvas.SmoothingMode = SmoothingMode.AntiAlias;
                    canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
                    MemoryStream m = new MemoryStream();
                    newImage.Save(m, ImageFormat.Jpeg);
                    return m.GetBuffer();
                }
            }
    
        }
    }
    
    private static Size CalculateDimensions(Size oldSize, int targetSize)
    {
        Size newSize = new Size();
        if (oldSize.Width > oldSize.Height)
        {
            newSize.Width = targetSize;
            newSize.Height = (int)(oldSize.Height * (float)targetSize / (float)oldSize.Width);
        }
        else
        {
            newSize.Width = (int)(oldSize.Width * (float)targetSize / (float)oldSize.Height);
            newSize.Height = targetSize;
        }
        return newSize;
    }
    

    谢谢你的帮助!

    3 回复  |  直到 13 年前
        1
  •  1
  •   BFree    15 年前

    首先想到的是,您是否考虑过多线程处理?例如,在单独的线程中为每个图像(或一批图像)调用此方法?这样,如果您的服务器有几个核心,您可以更快地完成工作。只是一个想法…

        2
  •  1
  •   Dan Byström    15 年前

    (穿线是一个很好的技巧。)

    尝试每次调用尽可能最小的图像作为输入的方法,而不是原始图像。如果原始图像是,比如说2000px,那么从中创建700px图像,然后使用新创建的700px图像创建500px等…

    使用高质量双三次设置,我怀疑您是否会注意到100px图像中的任何差异。(但它当然需要验证。)

        3
  •  1
  •   Tim Meers    13 年前

    为了完整性,这里是问题的第二部分的解决方案,这个问题从未被回答过。处理低分辨率图像时,图像被切断。现在的解决方案似乎很明显。问题在于上面这段代码:

    using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, 
                                                        PixelFormat.Format32bppRgb))
    

    问题是我选择的是像素格式,而不是原始图像的格式。正确的代码如下:

    public static byte[] ResizeImageFile(byte[] imageFile, int targetSize)
    {
        using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))
        {
            Size newSize = CalculateDimensions(oldImage.Size, targetSize);
    
        using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height,  
                                                            oldImage.PixelFormat))
        {
            newImage.SetResolution(oldImage.HorizontalResolution, 
                                                       oldImage.VerticalResolution);
            using (Graphics canvas = Graphics.FromImage(newImage))
            {
                canvas.SmoothingMode = SmoothingMode.AntiAlias;
                canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
                canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
                canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
                MemoryStream m = new MemoryStream();
                newImage.Save(m, ImageFormat.Jpeg);
                return m.GetBuffer();
            }
        }
    
       }
    }