我需要缩小高度或宽度大于预定义像素值的图像。
我编写了一些代码来查看原始图像,检查宽度,高度或高度和宽度是否大于最大宽度/最大高度设置。
我现在需要根据后一个值的最大值来确定要调整大小的尺寸。
例如:如果图片为900h x 300w
且MAX高度为700h
,我需要将高度调整为700
,将宽度调整为????
< - - 这是我需要计算的..
创建和保存图像文件很简单,超出了本文的范围:
// First I get the max height and width allowed:
int resizeMaxHeight = int.Parse(Utility.GetConfigValue("ResizeMaxHeight")); // in config: 700px
int resizeMaxWidth = int.Parse(Utility.GetConfigValue("ResizeMaxWidth")); // in config: 500px
// Save original:
try
{
filebase.SaveAs(savedFileName);
}
catch (System.IO.DirectoryNotFoundException ex)
{
Logger.Instance.LogException(ex, 0, "FileTransfer");
}
// Determin original dimensions:
Image image = System.Drawing.Image.FromFile(Server.MapPath(savedFileName));
int resizeHeight, resizeWidth;
bool doResize = true;
// both height and width are greater than the allowed height and width:
if (image.Width > resizeMaxWidth && image.Height > resizeMaxHeight)
{
if (image.Height > image.Width)
resizeHeight = resizeMaxHeight;
else
resizeWidth = resizeMaxWidth;
}
else if (image.Width > resizeMaxWidth)
{
// width is too great, but height is ok
resizeWidth = resizeMaxWidth;
}
else if (image.Height > resizeMaxHeight)
{
// height is too great, but width is ok
resizeHeight = resizeMaxHeight;
}
else
{
// image is ok size, don't resize:
doResize = false;
}
创建缩略图: 这就是我现在正在工作的......不完整的:
if (doResize)
{
ImageUtilities.ResizeImage(image, resizeWidth, resizeHeight);
}
答案 0 :(得分:14)
如果图像高度大于图像宽度,Nathaniel发布的解决方案实际上失败了。以下示例生成正确的结果:
private Size ResizeFit(Size originalSize, Size maxSize)
{
var widthRatio = (double)maxSize.Width / (double)originalSize.Width;
var heightRatio = (double) maxSize.Height/(double) originalSize.Height;
var minAspectRatio = Math.Min(widthRatio, heightRatio);
if (minAspectRatio > 1)
return originalSize;
return new Size((int)(originalSize.Width*minAspectRatio), (int)(originalSize.Height*minAspectRatio));
}
答案 1 :(得分:7)
以下是进行此计算的两种方法。根据您对问题的看法,可能看起来比另一个更直观。它们在数学上等效于几个小数位。
两者对Math.Round都是安全的,但只有ConstrainVerbose产生的结果总是小于maxWidth / maxHeight。
SizeF ConstrainConcise(int imageWidth, int imageHeight, int maxWidth, int maxHeight){
// Downscale by the smallest ratio (never upscale)
var scale = Math.Min(1, Math.Min(maxWidth / (float)imageWidth, maxHeight / (float) imageHeight));
return new SizeF(scale * imageWidth, scale * imageHeight);
}
SizeF ConstrainVerbose(int imageWidth, int imageHeight, int maxWidth, int maxHeight){
// Coalculate the aspect ratios of the image and bounding box
var maxAspect = (float) maxWidth / (float) maxHeight;
var aspect = (float) imageWidth / (float) imageHeight;
// Bounding box aspect is narrower
if (maxAspect <= aspect && imageWidth > maxWidth)
{
// Use the width bound and calculate the height
return new SizeF(maxWidth, Math.Min(maxHeight, maxWidth / aspect));
}
else if (maxAspect > aspect && imageHeight > maxHeight)
{
// Use the height bound and calculate the width
return new SizeF(Math.Min(maxWidth, maxHeight * aspect), maxHeight);
}else{
return new SizeF(imageWidth, imageHeight);
}
}
答案 2 :(得分:6)
您可以使用一些整数技巧来避免计算纵横比(并使用双精度数)..
// You have the new height, you need the new width
int orgHeight = 1200;
int orgWidth = 1920;
int newHeight = 400;
int newWidth = (newHeight * orgWidth) / orgHeight; // 640
...或
// You have the new width, you need the new height.
int orgWidth = 1920;
int orgHeight = 1200;
int newWidth = 800;
int newHeight = (newWidth * orgHeight) / orgWidth; // 500
以下示例将图像大小调整为任何所需的矩形(desWidth和desHeight),并将图像置于该矩形内。
static Image ResizeImage(Image image, int desWidth, int desHeight)
{
int x, y, w, h;
if (image.Height > image.Width)
{
w = (image.Width * desHeight) / image.Height;
h = desHeight;
x = (desWidth - w) / 2;
y = 0;
}
else
{
w = desWidth;
h = (image.Height * desWidth) / image.Width;
x = 0;
y = (desHeight - h) / 2;
}
var bmp = new Bitmap(desWidth, desHeight);
using (Graphics g = Graphics.FromImage(bmp))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(image, x, y, w, h);
}
return bmp;
}
答案 3 :(得分:2)
我为Bitmaps做了类似的事情,但想法是一样的:
1. get image height and width
2. get current screen resolution
3. calculate aspect ratio (ASR) from image size
Handle following cases:
4. if ASR >=1 and image width > image height
if image width > screen width {}
if image height > screen height {}
else if image width > screen width {}
else {}
else
if image height > screen height {}
else if image width > screen width {}
else {}
// SCREEN_SIZE是可配置的; Defs.SCREEN_SIZE = 100; //并且boolPixelAR为true;
请尝试以下代码:
// PERCENTAGE OF IMAGE -> TODO: Configurable? IMAZE ZOOM / SCREEN PERCENTAGE
Double HScale = __bmp.Width;// *Defs.SCREEN_SIZE / 100;
Double VScale = __bmp.Height;// *Defs.SCREEN_SIZE / 100;
Double __aspectRatio;
Double __screenRatio = _currentScreenSize.Width / _currentScreenSize.Height;
// PERCENTAGE OF SCREEN
if (!_boolPixelAR) {
HScale = _currentScreenSize.Width * Defs.SCREEN_SIZE / 100;
VScale = _currentScreenSize.Height * Defs.SCREEN_SIZE / 100;
}
else {
__aspectRatio = HScale / VScale;
if( __aspectRatio >= 1)
if (HScale >= _currentScreenSize.Width) { // Long Edge is WIDTH. For 100%, HScale = WIDTH
VScale = ((VScale * _currentScreenSize.Width) / HScale) * Defs.SCREEN_SIZE / 100;
HScale = _currentScreenSize.Width * Defs.SCREEN_SIZE / 100;
if (VScale > _currentScreenSize.Height) { // Long Edge is HEIGHT. For 100%, VScale = HEIGHT
//__aspectRatio = VScale / HScale;
HScale = ((HScale * _currentScreenSize.Height) / VScale) * Defs.SCREEN_SIZE / 100;
VScale = _currentScreenSize.Height * Defs.SCREEN_SIZE / 100;
}
}
else if (VScale > _currentScreenSize.Height) { // Long Edge is HEIGHT. For 100%, VScale = HEIGHT
//__aspectRatio = VScale / HScale;
HScale = ((HScale * _currentScreenSize.Height) / VScale) * Defs.SCREEN_SIZE / 100;
VScale = _currentScreenSize.Height * Defs.SCREEN_SIZE / 100;
}
else {
//Do nothing... Just set Zoom.
HScale = HScale * Defs.SCREEN_SIZE / 100;
VScale = VScale * Defs.SCREEN_SIZE / 100;
}
else
if (VScale > _currentScreenSize.Height) { // Long Edge is HEIGHT. For 100%, VScale = HEIGHT
//__aspectRatio = VScale / HScale;
HScale = ((HScale * _currentScreenSize.Height) / VScale) * Defs.SCREEN_SIZE / 100;
VScale = _currentScreenSize.Height * Defs.SCREEN_SIZE / 100;
}
else if (HScale >= _currentScreenSize.Width) { // Long Edge is WIDTH. For 100%, HScale = WIDTH
VScale = ((VScale * _currentScreenSize.Width) / HScale) * Defs.SCREEN_SIZE / 100;
HScale = _currentScreenSize.Width * Defs.SCREEN_SIZE / 100;
}
else {
//Do nothing... Just set Zoom.
HScale = HScale * Defs.SCREEN_SIZE / 100;
VScale = VScale * Defs.SCREEN_SIZE / 100;
}
////__aspectRatio = VScale / HScale;
//HScale = ((HScale * _currentScreenSize.Height) / VScale) * Defs.SCREEN_SIZE / 100;
//VScale = _currentScreenSize.Height * Defs.SCREEN_SIZE / 100;
}
Bitmap scaledBmp = GraphicsFactory.ResizeImage(
__bmp,
Convert.ToInt32(HScale),
Convert.ToInt32(VScale));
答案 4 :(得分:0)
将图像拟合为新尺寸需要两个操作:
调整大小 - 调整源图像的大小以恰好适合一个维度(宽度或高度 - 比率较小的那个)
裁剪 - 将上一个操作的结果裁剪为目标尺寸
这是一个小样本:
private static Image Resize(Image img, int width, int height)
{
Bitmap b = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage((Image)b))
{
g.DrawImage(img, 0, 0, width, height);
}
return (Image)b;
}
public static Image Crop(Image image, int width, int height)
{
int cropx = image.Width > width ? image.Width / 2 - width / 2 : 0;
int cropy = image.Height > height ? image.Height / 2 - height / 2 : 0;
width = image.Width > width ? width : image.Width;
height = image.Height > height ? height : image.Height;
Rectangle cropRect = new Rectangle(cropx, cropy, width, height);
var target = new Bitmap(cropRect.Width, cropRect.Height);
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(image, new Rectangle(0, 0, target.Width, target.Height), cropRect, GraphicsUnit.Pixel);
}
return target;
}
public static Image FitToSize(Image image, int width, int height)
{
var wratio = 1.0 * image.Width / width;
var hratio = 1.0 * image.Height / height;
int wresize;
int hresize;
if (wratio >= hratio && wratio > 1)
{
wresize = (int)Math.Round((double)image.Width / hratio);
hresize = height;
image = Resize(image, wresize, hresize);
image = Crop(image, width, height);
}
else if (hratio >= wratio && hratio > 1)
{
hresize = (int)Math.Round((double)image.Height / wratio);
wresize = width;
image = Resize(image, wresize, hresize);
image = Crop(image, width, height);
}
return image;
}