任何约会应用程序最关键的功能之一就是能够分享图片。我花了相当多的时间来梳理自己的(少数)好照片,把最好的部分剪下来。

唉,其他用户可以去查看我的个人资料,但他们看到的不是我裁剪的东西。

发生什么事了?好吧,像许多开发人员一样,我们一直在为如何使图像适合ImageView而努力。在本例中,我们的图像的比例类型为Center_Crop.,出现可以对于这张照片,但如果我们有一张非常高或非常宽的照片,就有可能遗漏一些重要的东西。

尽管有些很有帮助各种刻度类型的导轨,在这里都不起作用。我们希望根据用户裁剪的内容显示照片的特定部分,并且没有内置的缩放类型来帮助实现这一点。

滑行定制转换

在Ok188bet金宝搏官网Cupid我们用滑行由Bumptech进行图像加载。它是一个库,允许我们毫不费力地将图像从URL加载到ImageView中。滑翔不支持默认转换对于默认比例类型,例如安装中心Center_Crop.如果你需要它们。值得庆幸的是,对于那些需要的人来说,我们可以写自定义转换.

注意:for.有很多原因吗,您可以选择使用Square的Picasso而不是Glide进行图像加载。毕加索支持自定义转换下面的一些代码也将应用于该库。

根据glidewiki,编写其中一个的最简单方法是扩展bitmaptransformation.. 在我们开始讨论如何关注这个缩略图之前,让我们先看看我们将要开始的基础:

类CropTransformation(context:context):BitmapTransformation(context){override fun getId():String{return CropTransformation::class.java.name类}override fun transform(pool:BitmapPool,toTransform:Bitmap,outWidth:Int,outHeight:Int):位图{return toTransform}

我们需要重写两种方法。获取ID()确定转换的唯一ID。Glide缓存这些,所以您可能希望将其特定于您正在使用的图像的ID - 我们稍后会看到。转变(...)顾名思义,用于变换位图。这个totransform.参数是我们从中裁剪的原始位图。

要调用此转换,我们将其添加到滑动请求中:

滑翔(视图.上下文).load(uri).listener(侦听器).bitmapTransform(CropTransformation(视图.上下文)).into(视图)

缩略图输入

现在我们为我们的转型有一个骷髅课,我们知道裁剪原始位图。我们如何确定照片的缩略图坐标?

当我们调用服务器获取所有配置文件照片时,我们的响应可能如下(简化):

{原始:{宽度:404,高度:720},缩略图:{x:0,y:6,宽度:404,高度:404},标题:“一些标题”,url:“…”}

让我们逐一了解这些值:

  • 原始宽度:原始照片的宽度(以像素为单位)。
  • 原始高度:原始照片的高度(以像素为单位)。
  • 缩略图.x:缩略图相对于原始照片的起始x坐标。
  • 缩略图y:缩略图相对于原始照片的起始y坐标。
  • 缩略图宽度:缩略图相对于原始照片的宽度。
  • 缩略图高度:缩略图相对于原始照片的高度。

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

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

如果你仍然无法想象,它会像这样:

你的旅费可能会改变。您可以以其他一些JSON格式获取您的缩略图输入,但如果您从这六个值开始,则应适用以下规则。

可裁剪界面

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

界面可裁剪{val thumbnailX:Int val thumbnailY:Int val thumbnailWidth:Int val thumbnailHeight:Int val originalWidth:Int val originalHeight:Int}

现在,我们可以更新转换以获取此接口的实例。我们可以使用它来生成获取ID()方法唯一。我们还将为可裁剪字段创建新变量作为浮点,以避免任何整数除法。

类CropTransformation(context:context,private val photo:cropable):BitmapTransformation(context){/***返回转换的唯一标识符。Glide实际上缓存了这些,所以我们提供了*所有尺寸,以确保这张照片是独一无二的。*/override fun getId():字符串{return CropTransformation::class.java.name类+“宽度=${照片.拇指钉宽度}“+”高度=${照片.拇指钉高度}“+”x=${照片.thumbnailX}“+”y=${照片。拇指指甲}“+”原始宽度=${照片原始宽度}“+”原始高度=${照片原始高度}}重写fun transform(pool:BitmapPool,toTransform:Bitmap,outWidth:Int,outHeight:Int):位图{//如果没有要裁剪的内容,或者我们不知道原始大小,只需返回//。如果(照片.拇指钉宽度== 0 || 照片.拇指钉高度== 0 || 照片原始高度== 0 || 照片原始宽度==0){return toTransform}//将所有缩略图和原始值作为浮点值,以避免整数除法。值x=照片.thumbnailX.toFloat()值拇指=photo.thumbnailYtoFloat公司()值拇指宽度=照片.thumbnailWidth.toFloat()高度=图.thumbnailHeight.toFloat()值原始宽度=photo.originalWidth.toFloat图片()原值高度=photo.originalHeight.toFloat图片()//获取要从中剪切的位图的宽度和高度。val位图宽度=toTransform.width.toFloat转换()val位图高度=转换高度()返回转换}

从位图查找缩略图

以前,我们拨出了totransform.我们自定义转换中的参数作为我们将操纵的位图。我们可以通过致电获得这个位图的尺寸转换宽度转换高度. 但是,这些尺寸可能与我们的原始照片不同(尽管它应该保持纵横比)。

为了从位图中得到一个缩略图,我们必须做一些数学运算。知道我们的位图和原始照片有相同的纵横比,我们可以利用这一点,我们的优势。

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

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

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

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

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

//获取原始缩略图val startingLeftPercentage=thumbX/originalWidth val startingTopPercentage=thumbY/originalHeight//的起始点与边缘的距离百分比//使用起始百分比获取从val startingLeftPercentage=startingLeftPercentage*bitmapWidth val startingTop=startingTop百分比*bitmapHeight

创建新位图

既然我们有了这些值,我们就可以使用createbitmap.方法将其裁剪出来。

我们现在的完整转型看起来如此:

类裁剪(上下文:上下文,私有val照片:creampable):BitMapTransformation(上下文){/ ** *返回转换的唯一标识符。滑行实际上缓存了这些,所以我们提供*所有尺寸,以确保这张照片是独一无二的。* / override fun getID():string {return trackfransformation :: class.java.name +“width = $ {photo.thumbnailwidth}”+“height = $ {photo.thumbnailheight}”+“x = $ {photo.thumbnailx}“+”y = $ {photo.thumbnaily}“+”workingwidth = $ {photo.originalwidth}“+”原始= $ {photo.originalheight}“}覆盖有趣的变换(pool:bitmappool,totransform:bitmap,outwidth:int,Outheight:int):位图{//如果没有什么可以裁剪,或者我们不知道原始大小,只是返回//我们给出了什么。if(photo.thumbnailwidth == 0 || photo.thumbnailheight == 0 || photo.orginalheight == 0 || photo.originalwidth == 0){return totransform} //获取所有缩略图和原始值作为浮动以避免整数分裂。val thumbx = photo.thumbnailx.tofloat()val thumby = photo.thumbnailytofloat()val thumbwidth = photo.thumbnailwidth.tofloat()val thumbheight = photo.thumbnailheight.tofloat()val原创width.tofloat()val原创者= photo.orginalheight.tofloat()//获取我们将从中裁剪的位图的宽度和高度。val bitmapwidth = totransform.width.tofloat()val bitmapheight = totransform.height.tofloat()//获取原始缩略图Val LightLeftpercentege的边缘的起点距离的百分比= thumbx / OrationalWidth val启动器= thumby / apprictheight // 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()) } }

我们现在的用法如下:

滑翔(视图.上下文).load(uri).listener(侦听器).bitmapTransform(CropTransformation(视图.上下文,照片),进入(视图)

补充笔记

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

为什么它不完美融合?嗯,我们返回的位图的宽高比将是缩略图的纵横比。在这种情况下,它是404/404,或1.我们使用的图像视图具有〜1.6的纵横比。

输出纵横比可以用偏僻外面参数转变()方法。这个比率是外宽/外高. 您可以使用这些信息尝试缩放图像,使其更适合输出纵横比,但这对于另一篇博文来说是个数学问题。

这些自定义转换可以用于仅仅是裁剪。你可以找到一些酷图书馆与自定义转换在github上。

有任何疑问,或者想要分享您自己的一些很酷的转换?在推特上接触我@ Adammc331..想在Okcupid加入我吗?188bet金宝搏官网我们在招聘!