在处理从我们的某个服务器获取的嵌入式图像的功能时,其中一个要求是创建一个概览页面,其中显示所有图像,如iOS Native Photos App(正方形图块) ,以4/5的行和点击时,在屏幕范围内显示图像。
这已成功实施,但图像变形(图像方面从未被考虑过)。因此,他们要求我设计一种方法来裁剪图像,因此原始方面保持不变。
为了做到这一点,我想首先调整图像大小,直到宽度达到我想要的最大宽度((screenwidth - 10)/ 4 - 5)。
这是我目前使用的方法:
//Images is an array/List with base64 strings
foreach (var image in Images)
{
UIImage imageToAdd = UIImage.LoadFromData(NSData.FromArray(Convert.FromBase64String(image.Content)));
var width = imageToAdd.Size.Width;
var height = imageToAdd.Size.Height;
//GlobalSupport.ScreenWidth is a static variable that contains the actual screensize
var newWidth = (GlobalSupport.ScreenWidth - 10) / 4 - 5;
var newHeight = height * newWidth / width;
var widthToCrop = 0.0f;
var heightToCrop = 0.0f;
//If the new height is smaller than the new width, make the new height equal to the new width, and modify the new width accordingly.
if (newHeight < newWidth)
{
newHeight = newWidth;
newWidth = width * newHeight / height;
widthToCrop = newWidth - newHeight;
}
//Or, if the new height is greater than the new width, just crop the height.
else if (newHeight > newWidth)
{
heightToCrop = newHeight - newWidth;
}
UIGraphics.BeginImageContext(new SizeF(newWidth, newHeight));
var cropRectangle = new RectangleF(-widthToCrop, -heightToCrop, newWidth, newHeight);
imageToAdd.Draw(cropRectangle);
imageToAdd = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
UIButton btnToAdd = new UIButton(new RectangleF(-widthToCrop, -heightToCrop, newWidth, newHeight));
btnToAdd.SetBackgroundImage(imageToAdd, UIControlState.Normal);
btnToAdd.TouchUpInside += (sender, e) =>
{
Task.Factory.StartNew(() =>
{
//Displays a loading spinner
GlobalSupport.EnableLoadingOverlay(true, NSBundle.MainBundle.LocalizedString("txtOneMoment", "", ""));
}).ContinueWith(task => InvokeOnMainThread(() =>
{
//Navigate to the full-screen image viewer
this.NavigationController.PushViewController(
new VCDCMPhotoDetails(
UIImage.LoadFromData(
NSData.FromArray(
Convert.FromBase64String(image.Content)))), true);
GlobalSupport.EnableLoadingOverlay(false, "");
}));
};
//Add btn to the scrollable view's children
scrollView.AddSubview(btnToAdd);
}
此方法效果很好,除了一件事:如果new height
小于new width
,new height
和new width
成功修改,但在ImageToAdd.Draw(RectangleF)
之后{1}} Size
的{{1}}仍然具有ImageToAdd
值,而不是裁剪宽度(也就是说,如果我可以假设,如果我使用-20绘制图像作为其x值,宽度也会被修改为-20。
我不知道这是否是正确的方法。如果不是,那么欢迎所有帮助!如果这是正确的方法,但我错过了什么,请告诉我!提前谢谢!
裁剪图像时,x坐标等于图像的宽度减去缩略图的最大宽度:http://i.stack.imgur.com/uNm7k.png
裁剪后,图像仍然具有原始新宽度,而不是裁剪宽度:http://i.stack.imgur.com/rabeY.png
答案 0 :(得分:2)
使用目标图像大小的大小创建图像视图时,您最容易做到的事情。然后将图像设置为它并设置内容模式以缩放纵横填充,并简单地创建视图的屏幕截图(您可以在网上找到非常简单的解决方案)。
从你的问题我看不出你是否有任何问题或者是什么问题。但有一件事困扰着我。这条线
RectangleF(-widthToCrop, -heightToCrop, newWidth, newHeight)
将以您始终获得图像右下角的方式裁剪它。你应该把它放在中心位置:
RectangleF(-widthToCrop*0.5, -heightToCrop*0.5, newWidth, newHeight)
好的我觉得我找到了你的问题。您计算的框架是您应该在其上绘制图像以将其放在正方形上的框架。但是当你开始图像上下文时,你应该将大小设置为正方形。因此,如果宽度较大,则大小应为(newHeight, newHeight)
,否则为(newWidth, newWidth)
。按钮框对我来说也没有意义。为什么使用仅用于重绘图像的矩形?
答案 1 :(得分:2)
让我向您展示如何使用FILL操作裁剪图像的正确步骤。代码在Swift中,但是移植它应该没有问题:
public static func resampleImageToSize(image: UIImage!, size: CGSize) -> UIImage {
let originalWidth = image.size.width
let originalHeight = image.size.height
let originalRatio = originalWidth/originalHeight
let targetRatio = size.width/size.height
var targetFrame = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
if originalRatio>targetRatio {
// crop width
let targetHeight = size.height
let targetWidth = targetHeight * originalRatio
targetFrame = CGRect(x: (size.width-targetWidth)*0.5, y: (size.height-targetHeight)*0.5, width: targetWidth, height: targetHeight)
} else if originalRatio<targetRatio {
// crop height
let targetWidth = size.width
let targetHeight = targetWidth / originalRatio
targetFrame = CGRect(x: (size.width-targetWidth)*0.5, y: (size.height-targetHeight)*0.5, width: targetWidth, height: targetHeight)
}
UIGraphicsBeginImageContext(size)
image.drawInRect(targetFrame)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage
}
因此,这是一种采用原始图像并返回您选择尺寸的图像的通用方法。在您的情况下,这是您要显示的图标的大小。这里的操作是 fill ,如果您需要适合图像,您需要做的就是在{{1}中交换<
和>
语句。