任何约会软件最重要的功能之一就是分享图片。我花了相当多的时间梳理自己的(为数不多的)好照片,剪出最好的部分。

唉,其他用户可能会去查看我的个人资料,但他们看到的是不是我裁切掉。

发生了什么事?嗯,像许多开发人员一样,我们一直在纠结如何让图像适合ImageView。在本例中,图像的缩放类型为CENTER_CROP出现这好吧对于这张照片来说,但如果我们有一张非常高或非常宽的照片,就有可能遗漏一些重要的东西。

尽管有一些非常有帮助在各种规模类型的引导,没有人在这里工作。我们希望显示基于用户裁剪一下照片的特定部分,并没有内置的规模型,以帮助这一点。

滑翔自定义转换

我们使188bet金宝搏官网用OkCupid滑行通过Bumptech的图像加载。这是一个库,使我们能够毫不费力地从一个URL加载图像到一个ImageView的。滑翔不支持默认的转换默认缩放类型如FIT_CENTERCENTER_CROP如果你需要他们。值得庆幸的是,对于我们这些谁需要不止于此,我们可以写自定义的转换

注意:有很多原因,您可以选择与广场的毕加索,而不是滑行工作图像加载。毕加索有支持自定义的转换下面的一些代码也适用于该库。

根据Glide的Wiki,最简单的编写方法就是扩展BitmapTransformation。在我们进入大宗如何围绕这个缩略图,让我们看看在基地,我们将开始:

return CropTransformation::class.java.name}重写fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap {return toTransform}

我们需要重写两个方法。getId ()确定用于转化的唯一ID。滑翔缓存这些,所以你可能想给它一个ID具体到你正在使用的图像 - 以后我们会看到这一点。转变(...),顾名思义,是用来转换为位图。该toTransform参数是原来的位图,我们会从被裁剪。

要调用这个转变,我们将它添加到我们的滑翔要求:

Glide.with(view.context).load(URI).listener(受听者).bitmapTransform(CropTransformation(view.context)).into(视图)

缩略图输入

现在我们有我们的转型了一个框架类,我们知道原来的位图作物。我们如何确定我们的照片缩略图坐标?

当我们为所有的个人资料照片调用服务器时,我们的响应可能是这样的(简化):

{原:{宽度:404,高度:720},缩略图:{x: 0, y: 6,宽度:404,高度:404},标题:"Some caption ", url: "…"}

让我们逐一了解一下这些值:

  • 原创。宽度:原始照片的宽度,以像素为单位。
  • 原创。高度:原始照片的高度,以像素为单位。
  • thumbnail.x:起始x中的缩略图的坐标,相对于原始照片。
  • thumbnail.y: The starting y coordinate of the thumbnail, with respect to the original photo.
  • 缩略图。宽度:缩略图相对于原始照片的宽度。
  • 缩略图。高度:缩略图相对于原始照片的高度。

有了这些信息,让我们试着解释一下这个特定的用户是如何裁剪他们的照片的。

  1. 我们知道,缩略图是一个正方形,因为它是404x404。
  2. 我们知道缩略图和原图一样宽,因为原图是404x720。
  3. 我们知道缩略图与原始照片的左侧对齐是因为thumbnail.x等于0。
  4. 我们知道缩略图从照片顶部向下移动了6个像素,因为thumbnail.y等于6。

如果你还不能把它形象化,它应该是这样的:

你的旅费可能会改变。你可以让你的缩略图输入一些其他的JSON格式,但如果你有这六个值启动以下规则应该仍然适用。

Croppable接口

就我们的自定义转换而言,这是我们需要的所有信息。我们不关心图像url或任何其他方面——因此我们创建了一个接口来在定制转换中引用。如果你有多个照片模型,这个界面也很有帮助,只要他们仍然有必要的六个值:

接口Croppable {VAL thumbnailX的:int VAL thumbnailY的:int VAL thumbnailWidth的:int VAL thumbnailHeight的:int VAL originalWidth的:int VAL originalHeight的:int}

现在我们可以更新我们的转换,以获得这个接口的一个实例。属性返回的值getId ()方法独特。我们还将为我们Croppable领域的新变量作为花车以避免任何整数除法。

类CropTransformation(上下文:语境,私人VAL照片:Croppable):BitmapTransformation(上下文){/ ** *返回用于转化的唯一标识符。滑翔实际上缓存这些,所以我们提供*所有尺寸,以确保它是独一无二的照片。* /倍率乐趣的getId():字符串{返回CropTransformation :: class.java.name + “宽度= $ {photo.thumbnailWidth}” + “高度= $ {photo.thumbnailHeight}” +“X = $ {photo.thumbnailX}" + "y=${photo.thumbnailY}" + "originalWidth=${photo.originalWidth}" + "originalHeight=${photo.originalHeight}" } override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap { // If there's nothing to crop, or we don't know the original size, just return // what we were given. if (photo.thumbnailWidth == 0 || photo.thumbnailHeight == 0 || photo.originalHeight == 0 || photo.originalWidth == 0) { return toTransform } // Get all the thumbnail and original values as floats to avoid integer division. val thumbX = photo.thumbnailX.toFloat() val thumbY = photo.thumbnailYtoFloat() val thumbWidth = photo.thumbnailWidth.toFloat() val thumbHeight = photo.thumbnailHeight.toFloat() val originalWidth = photo.originalWidth.toFloat() val originalHeight = photo.originalHeight.toFloat() // Get the width and height of the bitmap we'll be cropping from. val bitmapWidth = toTransform.width.toFloat() val bitmapHeight = toTransform.height.toFloat() return toTransform } }

从位图找到缩略图

以前,我们叫了toTransform参数我们的自定义转换,我们会操纵位图。我们可以通过调用获得这个位图的尺寸toTransform.widthtoTransform.height。然而,这些尺寸可能与我们的原始照片不一样(尽管它应该保持高宽比)。

为了从位图中得到缩略图,我们需要做一些数学运算。知道我们的位图和原始照片有相同的长宽比,我们可以利用这一点。

让我们开始计算我们需要裁剪的宽度/高度。缩略图的宽度和高度是多少,作为原始照片的百分比?

VAL thumbWidthPercentage =(thumbWidth / originalWidth)// 1 VAL thumbHeightPercentage =(thumbHeight / originalHeight)// 0.5611

现在我们知道了这一点,我们可以计算缩略图的宽度/高度与原始位图的关系。我们只是将这个百分比分别乘以位图的宽度/高度。

//将与位图宽度相同。val newWidth = thumbwidth百分比* bitmapWidth //将略大于位图高度的一半。val newHeight = thumbheight百分比*位图高度

我们可以用同样的方法来计算新的起始x/y坐标-得到它们的距离作为原始照片的百分比,然后用这个百分比来找到它们在位图中的对应点:

/ /得到起始点的距离百分比原缩略图边缘的val startingLeftPercentage = thumbX / originalWidth val startingTopPercentage = thumbY / originalHeight / /开始使用百分比的起始坐标对/ /位图我们种植从val startingLeft = startingLeftPercentage * bitmapWidth val startingTop = startingTopPercentage * bitmapHeight

创建新位图

现在我们有了这些值,我们可以使用createBitmap方法来裁剪它。

我们的全面转型,现在看起来是这样的:

类CropTransformation(上下文:语境,私人VAL照片:Croppable):BitmapTransformation(上下文){/ ** *返回用于转化的唯一标识符。滑翔实际上缓存这些,所以我们提供*所有尺寸,以确保它是独一无二的照片。* /倍率乐趣的getId():字符串{返回CropTransformation :: class.java.name + “宽度= $ {photo.thumbnailWidth}” + “高度= $ {photo.thumbnailHeight}” +“X = $ {photo.thumbnailX}" + "y=${photo.thumbnailY}" + "originalWidth=${photo.originalWidth}" + "originalHeight=${photo.originalHeight}" } override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap { // If there's nothing to crop, or we don't know the original size, just return // what we were given. if (photo.thumbnailWidth == 0 || photo.thumbnailHeight == 0 || photo.originalHeight == 0 || photo.originalWidth == 0) { return toTransform } // Get all the thumbnail and original values as floats to avoid integer division. val thumbX = photo.thumbnailX.toFloat() val thumbY = photo.thumbnailYtoFloat() val thumbWidth = photo.thumbnailWidth.toFloat() val thumbHeight = photo.thumbnailHeight.toFloat() val originalWidth = photo.originalWidth.toFloat() val originalHeight = photo.originalHeight.toFloat() // Get the width and height of the bitmap we'll be cropping from. val bitmapWidth = toTransform.width.toFloat() val bitmapHeight = toTransform.height.toFloat() // Get the percent distance of the starting points from the edges for the original thumbnail val startingLeftPercentage = thumbX / originalWidth val startingTopPercentage = thumbY / originalHeight // Use the starting percentages to get the starting coordinates with respect to the // bitmap we're cropping from val startingLeft = startingLeftPercentage * bitmapWidth val startingTop = startingTopPercentage * bitmapHeight // Figure out the percentage width/height of the thumbnail with respect to the original image val thumbWidthPercentage = thumbWidth / originalWidth val thumbHeightPercentage = thumbHeight / originalHeight // Use that percentage to calculate the width/height to crop from the given bitmap val newWidth = thumbWidthPercentage * bitmapWidth val newHeight = thumbHeightPercentage * bitmapHeight // Create a bitmap by cropping out our new width/height begin at our starting coordinates. return Bitmap.createBitmap( toTransform, startingLeft.toInt(), startingTop.toInt(), newWidth.toInt(), newHeight.toInt()) } }

我们现在的用法是这样的:

滑动.with(view.context) .load(uri) .listener(listener) . bitmaptransform (CropTransformation(view) .背景图)).into(视图)

补充说明

这种方法对我们缩小图像的重要部分非常有效。在这之后,我们只使用中心裁剪缩放类型使缩略图适合我们的ImageView。

为什么它不合身?好了,我们的位图回报的长宽比将缩略图的纵横比。在这种情况下它是404分之404,或1。ImageView的我们使用了〜1.6的纵横比。

输出长宽比可以通过使用计算outWidthoutHeight的PARAMS转变()方法。这个比率是outWidth / outHeight。您可以使用此信息来尝试,更扩展您的图像,使其适合输出的宽高比,但这是一些数学的另一篇博客。

这些定制的转换,可用于远不止裁剪。你可以找到一些很酷与自定义转换库在GitHub上。

有任何疑问,或希望分享自己的一些很酷的转变?伸手到我的Twitter@ AdamMc331。想和我一起在OkCupid?188bet金宝搏官网我们招聘!