首页 文章

在C#中调整位图大小

提问于
浏览
0

我正在寻找一种方法来调整位图的大小,而不会失去其实际形状,同时要记住新的大小与原始图像尺寸不成比例 .

确切地说,我想调整直立八(40x110)到29x29位图的图像,我正在寻找一个函数来将原始比例转换为相对于其新图像,同时用白色填充新创建的空间(宽度)具有与实际八个相同的侧面间隙到其白色基线 .

不幸的是,这不符合我的要求:

public static Bitmap ResizeImage(Image image, int width, int height)
    {
        var destRect = new Rectangle(0, 0, width, height);
        var destImage = new Bitmap(width, height);

        destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

        using (var graphics = Graphics.FromImage(destImage))
        {
            graphics.CompositingMode = CompositingMode.SourceCopy;
            graphics.CompositingQuality = CompositingQuality.HighQuality;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

            using (var wrapMode = new ImageAttributes())
            {
                wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
            }
        }

        return destImage;
    }

Update 1: 比例调整大小的新功能:

public static Bitmap ResizeImageProportional(Bitmap bitmap, int width, int height)
    {
        Bitmap destImage;
        Rectangle destRect;
        int destH, destW, destX, dextY;

        if (bitmap.Height > bitmap.Width)
        {
            destH = height;
            destW = bitmap.Width / bitmap.Height * height;
            destX = (width - destW) / 2;
            dextY = 0;
        }
        else if (bitmap.Height < bitmap.Width) 
        {
            destH = bitmap.Height / bitmap.Width * width;
            destW = width;
            destX = 0;
            dextY = (height - destH) / 2;
        }
        else
        // if (bitmap.Width == bitmap.Height)
        {
            destH = height;
            destW = width;
            destX = 0;
            dextY = 0;
        }

        destRect = new Rectangle(destX, dextY, destW, destH);
        destImage = new Bitmap(width, height);

        destImage.SetResolution(bitmap.HorizontalResolution, bitmap.VerticalResolution);

        using (var graphics = Graphics.FromImage(destImage))
        {
            graphics.CompositingMode = CompositingMode.SourceCopy;
            graphics.CompositingQuality = CompositingQuality.HighQuality;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

            using (var wrapMode = new ImageAttributes())
            {
                wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                graphics.DrawImage(bitmap, destRect, 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, wrapMode);
            }
        }

        return destImage;
    }

不幸的是,我总是用这个解决方案获得一个空位图 . 我首先将原始位图裁剪为一个矩形,其中我的位图元素确实适合 . 否则,位图本身的左侧基线也是其中图形元素的基线,而整个背景为白色 . 然后我将这个位图(大约40x80)放入“ResizeImageProportional”(原始后编辑 . )函数中,其宽度和高度值为29 .

1 回答

  • 0

    如果你想保持计算目标rectnagle所需的比例 .

    以下是我头脑中的措施:

    destH = height;
    destW = image.Width / image.Height * height; 
    destX = (width - destW) / 2;
    dextY = 0;
    

    你应该清除你想要的颜色背景: Graphics.Clear(someColor);

    如果不这样做,则使用源图像和目标图像的边界,从而扭曲图像 . 你似乎有什么......,不是吗?

    在那种情况下,当然没有新的空间 .

    计算时,必要时使用float .

    Update:

    也许您想要分析原始图像并保留或删除前景到边缘的空格 . 这意味着既可以查看像素,也可以回过头来创建原始图片 .

    enter image description here

    对于示例,我添加了图的边界 .

    这是一个简单的裁剪功能;它假定左上角保持背景颜色并返回一个裁剪矩形:

    public static Rectangle CropBounds(Image image)
    {
        Bitmap bmp = (Bitmap)image;
        int x0 = 0;
        int x1 = bmp.Width - 1;
        int y0 = 0;
        int y1 = bmp.Height - 1;
        Color c = bmp.GetPixel(0, 0);
        while (x0==0)
        {  for (int x = 0; x < x1; x++)
                if ((x0==0)) for (int y = 0; y < y1; y++)
                    if ( bmp.GetPixel(x,y)!= c) {x0 = x-1; break;} }
        while (x1 == bmp.Width - 1)
        {
            for (int x = bmp.Width - 1; x > 0; x--)
                if ((x1 == bmp.Width - 1)) for (int y = 0; y < y1; y++)
                        if (bmp.GetPixel(x, y) != c) { x1 = x + 1; break; }  }
        while (y0 == 0)
        {
            for (int y = 0; y < y1; y++)
                if ((y0 == 0)) for (int x = 0; x < bmp.Width; x++)
                        if (bmp.GetPixel(x, y) != c) { y0 = y - 1; break; }
        }
        while (y1 == bmp.Height - 1)
        {
            for (int y = bmp.Height - 1; y > 0; y--)
                if ((y1 == bmp.Height - 1)) for (int x = 0; x < bmp.Width; x++)
                        if (bmp.GetPixel(x, y) != c) { y1 = y + 1; break; }
        }
    
        return new Rectangle(x0, y0, x1 - x0, y1 - y0);
    }
    

    现在您可以更改代码以使用它:

    graphics.DrawImage(image, destRect, CropBounds(image) , GraphicsUnit.Pixel);
    

    如果你真的需要翻转,只需存储矩形并更改为适当的格式..!

    Update 2:

    有一个原因我写的时候计算,必要时使用float ..:

    ResizeImageProportional 函数中,您需要避免整数精度损失!将分部更改为:

    destW = (int) (1f * bitmap.Width / bitmap.Height * height);
    

    destH =  (int) (1f *bitmap.Height / bitmap.Width * width);
    

相关问题