在上传时调整宽度,并保持高度比例
本文关键字:高度 调整 | 更新日期: 2023-09-27 18:14:52
我使用以下系统绘图代码来调整上载图像的大小。问题是,风景或肖像图像失真,因为系统绘图使他们成为方形。是否有可能仅调整宽度并保持高度成比例?以及如何?由于
HttpPostedFile imageFile = UploadImages.PostedFile;
System.Drawing.Image ri = System.Drawing.Image.FromStream(imageFile.InputStream);
ri = ResizeBitmap((Bitmap) ri, 200, 200);
private Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
{
Bitmap result = new Bitmap(nWidth, nHeight);
using (Graphics g = Graphics.FromImage((System.Drawing.Image)result))
g.DrawImage(b, 0, 0, nWidth, nHeight);
return result;
}
如果你想创建一个新的位图,宽度为200像素,高度按比例缩放,你可以这样做:
private static int CalculateProportionalHeight(int oldWidth, int oldHeight, int newWidth)
{
if (oldWidth <= 0 || oldHeight <= 0 || newWidth <= 0)
// For safety.
return oldHeight;
double widthFactor = (double)newWidth / (double)oldWidth;
int newHeight = (int)Math.Round(widthFactor * (double)oldHeight);
if (newHeight < 1)
newHeight = 1; // just in case.
return newHeight;
}
private static Bitmap ResizeBitmap(Bitmap b, int nWidth)
{
int nHeight = CalculateProportionalHeight(b.Width, b.Height, nWidth);
Bitmap result = new Bitmap(nWidth, nHeight);
using (Graphics g = Graphics.FromImage((System.Drawing.Image)result))
g.DrawImage(b, 0, 0, nWidth, nHeight);
return result;
}
或者你想创建一个200x200的位图,将旧图像缩放到适合内部,并在必要时使用字母框?
如果你想创建一个固定的200x200大小的图像,并按比例缩小图像以适合和有字母框,应该这样做:
static RectangleF PlaceInside(int oldWidth, int oldHeight, int newWidth, int newHeight)
{
if (oldWidth <= 0 || oldHeight <= 0 || newWidth <= 0 || newHeight <= 0)
return new RectangleF(oldWidth, oldHeight, newWidth, newHeight);
float widthFactor = (float)newWidth / (float)oldWidth;
float heightFactor = (float)newHeight / (float)oldHeight;
if (widthFactor < heightFactor)
{
// prefer width
float scaledHeight = widthFactor * oldHeight;
// new new RectangleF(x, y, width, height)
return new RectangleF(0, (newHeight - scaledHeight) / 2.0f, newWidth, scaledHeight);
}
else
{
// prefer height
float scaledWidth = heightFactor * oldWidth;
// new new RectangleF(x, y, width, height)
return new RectangleF((newWidth - scaledWidth) / 2.0f, 0, scaledWidth, newHeight);
}
}
private static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
{
int oldWidth = b.Width;
int oldHeight = b.Height;
Bitmap result = new Bitmap(nWidth, nHeight);
using (Graphics g = Graphics.FromImage((System.Drawing.Image)result))
{
var box = PlaceInside(oldWidth, oldHeight, nWidth, nHeight);
g.DrawImage(b, box);
}
return result;
}
更新2
这里有一个版本,它创建了一个宽度为200,高度为横向比例的图像,高度为200,宽度为纵向比例的图像:
private static Bitmap ResizeBitmapUpto(Bitmap b, int nWidth, int nHeight, System.Drawing.Drawing2D.InterpolationMode interpolationMode)
{
int oldWidth = b.Width;
int oldHeight = b.Height;
var box = PlaceInside(oldWidth, oldHeight, nWidth, nHeight);
int actualNewWidth = (int)Math.Max(Math.Round(box.Width), 1);
int actualNewHeight = (int)Math.Max(Math.Round(box.Height), 1);
Bitmap result = new Bitmap(actualNewWidth, actualNewHeight);
using (Graphics g = Graphics.FromImage((System.Drawing.Image)result))
{
g.InterpolationMode = interpolationMode;
g.DrawImage(b, 0, 0, actualNewWidth, actualNewHeight);
}
return result;
}
我添加了一个interpolationMode,这样你就可以根据Ksv3n的答案试验不同的质量。
(希望)最后更新
下面是我用来验证代码的测试设置。我可以在我的电脑上成功地打开、调整大小和保存各种图像。
public static void TestResizeBitmapUpto(string file, string newFile)
{
try
{
using (var image = Bitmap.FromFile(file))
{
if (image == null)
return;
using (Bitmap b = new Bitmap(image))
{
using (var newBitmap = ResizeBitmapUpto(b, 200, 200, System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor))
{
newBitmap.Save(newFile);
}
}
}
}
catch (System.IO.FileNotFoundException e)
{
Debug.WriteLine(e.ToString());
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
您的代码中缺少的是:
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
这里是你可以使用的方法来调整你的图像大小,保持它的比例:
private Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
{
Bitmap result = new Bitmap(nWidth, nHeight);
using (Graphics g = Graphics.FromImage((System.Drawing.Image)result))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.DrawImage(b, 0, 0, nWidth, nHeight);
}
return result;
}
DrawImage会将图像拉伸到你所定义的(在你的例子中是200/200,这是一个正方形)。
你需要计算nWidth和nHeight的实际值:
// original image (b.Width, b.Height)
double originalWidth = 200;
double originalHeight = 100;
// user defined wanted width
double wantedWidth = 200; // nWidth parameter to your method
double wantedHeight = 300; // nHeight parameter to your method
double ratioW = originalWidth / wantedWidth;
double ratioH = originalHeight / wantedHeight;
double ratio = Math.Max(ratioW, ratioH);
// rectangle proportional to the original that fits into the wanted
double destinationWidth = originalWidth / ratio; // what you pass to DrawImage as nWidth
double destinationHeight = originalHeight / ratio; // what you pass to DrawImage as nWidth
它所做的是计算原始图像和想要的图像的宽度和高度比,并取其最大值。使用它来划分原始值,这将使它们完全适合所需的矩形。
这将绘制缩放后的图像,根据方向向上或向左对齐,因为最终图像将等于或大于所需图像或原始图像。为了使其在最终图像中居中,您需要调整DrawImage()的左坐标和顶部坐标,方法是取宽度/高度的差值并除以2。
如果结果图像的大小可以不同于用户指定的(nWidth/nHeight),那么你可以简单地用destinationWidth/Height初始化它,并返回它,而不需要居中