关于Fresco加载图片的处理,例如旋转、裁剪切割图片,在官方文档也都有提到,只是感觉写的不太详细,正好最近项目里有类似需求,所以分享一些使用小tip,后面的朋友就不用再走弯路浪费时间了。(测试图片分辨率1200*800)

原图:

###旋转图片

/*** 旋转图片** @param rotate ,例如:RotationOptions.ROTATE_90*/private void rotate(SimpleDraweeView img, int rotate) {RotationOptions rotationOptions = RotationOptions.forceRotation(rotate);ImageRequest build = ImageRequestBuilder.newBuilderWithSource(getUriForFresco(this, R.mipmap.test_img)).setRotationOptions(rotationOptions).build();PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder().setImageRequest(build).build();mImageView.setController(controller);}
复制代码

使用效果:

###监听图片下载 首先构造监听器:

//监听图片下载进度,这里只重写了onFinalImageSet,当图片下载完成时获得图片宽高等信息
ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {@Overridepublic void onFinalImageSet(String id, com.facebook.imagepipeline.image.ImageInfo imageInfo, Animatable animatable) {int viewWidth = imageInfo.getWidth();int viewHeight = imageInfo.getHeight();Toast.makeText(MainActivity.this, viewWidth + "--" + viewHeight, Toast.LENGTH_SHORT).show();}};
复制代码
/*** 获得图片宽高** @param controllerListener 图片下载监听器*/
private void getImageInfo(ControllerListener<? super ImageInfo> controllerListener) {PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder().setControllerListener(controllerListener).setUri(getUriForFresco(this, R.mipmap.test_img)).build();mImageView.setController(controller);
}
复制代码

###如果我想要1:1在手机端展示呢? 我首先想到的是1:1按照图片的尺寸设置SimpleDraweeView的宽高并设置缩放方式为fitXY,但是果不其然,view超出屏幕的部分是无效的。

###裁剪切割图片

既然view超出屏幕无效,那就曲线救国,让图片超出屏幕部分不显示在view里就好了。 裁剪图片首先要写一个processor类:

/*** 切割图片processor类* 四个成员变量和createBitmap时的参数一致,即起点的X/Y坐标、要裁剪的宽高。因为项目里还涉及到缩放,所以我调整了下参数设成百分比方便换算*/
public class CutProcess extends BasePostprocessor {private float mBeginXPercent;private float mBeginYPercent;private float mCutWidthPercent;private float mCutHeightPercent;public CutProcess(float beginXPercent, float beginYPercent, float cutWidthPercent, float cutHeightPercent) {this.mBeginXPercent = beginXPercent;this.mBeginYPercent = beginYPercent;this.mCutWidthPercent = cutWidthPercent;this.mCutHeightPercent = cutHeightPercent;}@Overridepublic CloseableReference<Bitmap> process(Bitmap sourceBitmap,PlatformBitmapFactory bitmapFactory) {int viewWidth = sourceBitmap.getWidth();int viewHeight = sourceBitmap.getHeight();int beginx = (int) (mBeginXPercent * viewWidth);int beginy = (int) (mBeginYPercent * viewHeight);int width = (int) (mCutWidthPercent * viewWidth);int height = (int) (mCutHeightPercent * viewHeight);CloseableReference<Bitmap> bitmapRef = bitmapFactory.createBitmap(sourceBitmap, beginx, beginy, width, height);return CloseableReference.cloneOrNull(bitmapRef);}
}
复制代码

然后在ImageRequest里setProcessor:

/*** 裁剪图片* @param processor*/private void cutPic(BasePostprocessor processor) {ImageRequest build = ImageRequestBuilder.newBuilderWithSource(getUriForFresco(this, R.mipmap.test_img)).setPostprocessor(processor).build();PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder().setImageRequest(build).build();mImageView.setController(controller);}
复制代码

调用方法:

mImageView.setLayoutParams(new RelativeLayout.LayoutParams(600, 400));
CutProcess cutProcess = new CutProcess(0, 0, 0.5f, 0.5f);
cutPic(cutProcess);
复制代码

图片是1200800的,这里设置view的宽高为600400,可以看到图片成功裁剪只保留原图左上四分之一。通过设置view宽高,配合裁剪图片,即可达到1:1显示的效果。

###旋转+裁剪 如果是要旋转90度后再裁剪呢?那还不简单,直接在裁剪的基础上,在ImageRequest里调用旋转方法不就好了。

/*** 旋转+裁剪图片* @param processor*/private void rotateAndcutPic(BasePostprocessor processor, int rotate) {RotationOptions rotationOptions = RotationOptions.forceRotation(rotate);ImageRequest build = ImageRequestBuilder.newBuilderWithSource(getUriForFresco(this, R.mipmap.test_img)).setPostprocessor(processor).setRotationOptions(rotationOptions).build();PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder().setImageRequest(build).build();mImageView.setController(controller);}
复制代码

然后调用:

//例如我需要旋转90度且宽度不变,高度方向裁剪掉一半(即保留(0,0)-(1200,400))
mImageView.setLayoutParams(new RelativeLayout.LayoutParams(400, mScreenHeight));
CutProcess cutProcess = new CutProcess(0, 0, 1f, 0.5f);
rotateAndcutPic(cutProcess, RotationOptions.ROTATE_90);
复制代码

然而得到的并不是我们想要的

可以看到得到的是左半边(0,0)-(600,800)的图,即宽度方向被裁剪掉一般,高度方向不变,明明我在cutProcess里是设置宽度方向不变,高度方向裁剪50%,但是因为旋转了90度,结果却正好相反。难道是因为旋转90度后横纵方向也发生改变?那调换一下横纵方向的切割比例试试看:

CutProcess cutProcess = new CutProcess(0, 0, 0.5f, 1f);
rotateAndcutPic(cutProcess, RotationOptions.ROTATE_90);
复制代码

可以看到,调换横纵切割比例后,却得到的是下半边(0,400)-(1200,800)。还是不正确,难道是原点也改变了?再测试一下,如果要裁剪后保留右下四分之一(600,400)-(1200,800)区域,正常无旋转的情况下是这样的:

mImageView.setLayoutParams(new RelativeLayout.LayoutParams(600, 400));
CutProcess cutProcess = new CutProcess(0.5f, 0.5f, 0.5f, 0.5f);
rotateAndcutPic(cutProcess, RotationOptions.NO_ROTATION);
复制代码

但如果旋转270度后,同样代码得到的结果却是这样的:

看到这里我们就清楚了,旋转图片后,其实(0,0)点,也就是所谓的原点也随之变换。默认情况下,原点是(0,0),顺时针旋转90度后,原点就变成了(0,800),以此类推旋转180度原点为(1200,800),旋转270度原点为(1200,0)(和旋转后的图片的左上角相对应)。虽然是在构建ImageRequest时同时传入旋转和裁剪参数的,但实际上可以看作是先完成了旋转,然后在旋转后的基础上,以屏幕的左上角为原点,左上角往右为x正方向,左上角往下为y正方向。

小试牛刀一下,旋转270度后,想要裁剪后只保留原图的左上四分之一(0,0)-(600,600),那推测就应该是(0, 0.5f, 0.5f, 0.5f)。

mImageView.setLayoutParams(new RelativeLayout.LayoutParams(400, 600));
CutProcess cutProcess = new CutProcess(0, 0.5f, 0.5f, 0.5f);
rotateAndcutPic(cutProcess, RotationOptions.ROTATE_270);
复制代码

Bingo!推测正确。

旋转+裁剪就是这个原点的变换要注意下。另外看代码里的几个方法,裁剪、旋转、获得宽高等,有没有觉得老是要重复写PipelineDraweeController、ImageRequest的代码好麻烦啊。其实裁剪、旋转等方法无非也就是添加一个参数,类似这种可变参数的复杂类的构造可以使用Builder模式封装一下。封装代码就不贴在这里了。demo下载地址

//Builder模式封装后
new FrescoBuilder(mImageView, getUriForFresco(this, R.mipmap.test_img)).cutPic(0f, 0.5f, 0.5f, 0.5f) //裁剪.setRotate(RotationOptions.ROTATE_270) //旋转.setControllerListener(controllerListener) //设置监听.build();
复制代码

使用Matrix实现

继承SimpleDraweeView自定义控件,使用Matrix实现旋转缩放:

public class MyFresco extends SimpleDraweeView {private Matrix mMatrix;private float mScaleX = 1f;private float mScaleY = 1f;private int mViewWidth = -1;private int mViewHeight = -1;private RectF mDisplayRect = new RectF();private int mDegree = -1;public MyFresco(Context context, GenericDraweeHierarchy hierarchy) {super(context, hierarchy);init();}public MyFresco(Context context) {super(context);init();}public MyFresco(Context context, AttributeSet attrs) {super(context, attrs);init();}public void setViewInfo(int width, int Height) {mViewWidth = width;mViewHeight = Height;}private void init() {mMatrix = new Matrix();mMatrix.postScale(mScaleX, mScaleY);}/*** 缩放* @param scaleX 缩放倍数*/public void setScale(float scaleX, float scaleY) {mScaleX = scaleX;mScaleY = scaleY;mMatrix.postScale(scaleX, scaleY);invalidate();}/*** 旋转* @param degree 角度*/public void rotate(int degree) {if (mDegree == -1) {mDegree = degree;if (mDegree != 0) {mMatrix.postRotate(degree);invalidate();if (mDegree == 90) {//旋转后图片超出边界,所以要再做平移mMatrix.postTranslate(getRectWidth(), 0);} else if (mDegree == 180) {mMatrix.postTranslate(getRectWidth(), getRectHieght());} else if (mDegree == 270) {mMatrix.postTranslate(0, getRectHieght());}}} else {mDegree += degree;mMatrix.postRotate(degree); //getRectWidth是旋转后的widthinvalidate();mMatrix.postTranslate(getRectWidth(), 0);}invalidate();}/*** 还原设置*/public void reset() {mScaleX = 1f;mScaleY = 1f;mMatrix = new Matrix();mMatrix.setScale(mScaleX, mScaleY);mViewWidth = -1;mViewHeight = -1;mDegree = -1;}/*** 获得旋转后超出边界的高度* @return*/public float getRectHieght() {RectF displayRect = getDisplayRect(mMatrix);if (displayRect != null) {return displayRect.height();} else {return -1;}}/*** 获得旋转后超出边界的宽度* @return*/public float getRectWidth() {RectF displayRect = getDisplayRect(mMatrix);if (displayRect != null) {return displayRect.width();} else {return -1;}}private RectF getDisplayRect(Matrix matrix) {if (mViewWidth == -1 || mViewHeight == -1) {return null;}mDisplayRect.set(0.0F, 0.0F, mViewWidth, mViewHeight);getHierarchy().getActualImageBounds(mDisplayRect);//将matrix映射到rectfmatrix.mapRect(mDisplayRect);return mDisplayRect;}@Overrideprotected void onDraw(Canvas canvas) {int save = canvas.save();canvas.concat(mMatrix);super.onDraw(canvas);canvas.restoreToCount(save);}
}复制代码

就是酱~

Fresco 二三事:图片处理之旋转、缩放、裁剪切割图片相关推荐

  1. VS+Qt应用开发-Qt+Halcon显示图片,实现鼠标缩放、移动图片

    VS+Qt应用开发-Qt+Halcon显示图片,实现鼠标缩放.移动图片 效果展示 界面设计 代码例程 完整代码 CMyLabel.h CMyLabel.cpp BrowsePic.h BrowsePi ...

  2. html如何图片立体自动旋转,css3如何让图片不停旋转?

    本篇文章将要给大家详细介绍如何使用css3让图片实现不停旋转的效果,我们在进行网页页面设计时,经常会遇到各种关于图片展示的问题,比如有的需要让图片圆角展示.图片点击放大展示等等效果. 下面主要就给大家 ...

  3. iOS transform解决连续多次旋转缩放,实现图片旋转缩放效果

    一.需求 实现imageView的缩放旋转效果,一般有两种方式: 1.底层加scrollview,利用scrollview的属性实现.(推荐这种,这是我比较后发现的,手势做缩放旋转会有点弊端) 2.利 ...

  4. iOS开发点击查看图片详情并可缩放拖拽图片长按图片下载

    由图片缩略图进入查看图片原图页面,并可对图片进行缩放(最小不小于原图,最大不大于三倍原图),长按可保存到本地相册或者查看原图. 1)缩略图页面: 2)点击查看原图页面 代码部分: 1.初始化图片背景跟 ...

  5. html如何图片立体自动旋转,html5如何实现图片的3D旋转效果

    html5如何实现图片的3D旋转效果 发布时间:2020-12-01 09:54:40 来源:亿速云 阅读:192 作者:小新 小编给大家分享一下html5如何实现图片的3D旋转效果,希望大家阅读完这 ...

  6. VS+Qt+Halcon——显示图片,实现鼠标缩放、移动图片

    摘要 本篇博文记录一下,用VS+Qt+Halcon实现对图片的读取以及鼠标缩放,移动(鼠标事件调用了halcon自带的算子)的过程.以及遇到的坑.....

  7. html 里img图片被自动旋转,关于HTML5显示图片翻转90度的问题

    首先,看到标题就觉得这个问题有点看不懂吧.咱遇到问题,那就解决问题.下面就具体描述一下遇到的情况. 上传作品后,需要作品的详情展示,然后在预览页面,出现某些图片与上传的图片展示不一致的效果.下面是原图 ...

  8. java 图片合成 工具类_Java实现的微信图片处理工具类【裁剪,合并,等比例缩放等】...

    本文实例讲述了Java实现的微信图片处理工具类.分享给大家供大家参考,具体如下: 现在 外面核心,图片文章比较少,看了拷贝代码,而用不了,用相应jar包处理,很多等比例缩放,达不到 想要的给予的期望: ...

  9. linux jpg图片缩放,ImageMagick之图片缩放

    利用ImageMagicK的convert命令,能很方便的实现图片的放大缩小,可以进行等比例缩放,也能缩放到指定的固定大小.缩放的参数resize,由它来指定缩放后图片的宽高,比如"200× ...

最新文章

  1. python excel行数_使用python计算excel中的行数
  2. 你真的了解try{ return }finally{}中的return?
  3. Boost.Asio使用实例
  4. mysql 删除原理_MySQL权限原理及删除MySQL的匿名账户
  5. ActiveMQ入门案例-生产者代码实现
  6. python_魔法方法(六):迭代器和生成器
  7. unicode 与 utf-8
  8. 继承方式与成员属性的访问关系表
  9. vue中进入详情页记住列表滚动位置keep-alive解决
  10. Ubuntu下Android Studio连接手机无法识别
  11. Dynamics AX2012 SSRS报表添加功能(通用)
  12. php 调用拼多多接口方法 生成 sign方法
  13. 基站的小区号256变换
  14. 你觉得最好用的地图导航软件是哪一个?这3款App供你选择
  15. 排列组合思维导图_巧用思维导图做数学单元整理
  16. Update join 修正数据
  17. 我的分享:第九章:月薪三万执行计划
  18. STM32/CPU总线的由来和地址映射概念
  19. 有苦有乐的算法 --- 计数排序
  20. Root mapping definition has unsupported parameters

热门文章

  1. CTF-杂项题-伪加密
  2. java hibernate 多对多_java - hibernate多对多问题
  3. matlab 计算汉明距_matlab实现滑动平均滤波
  4. python求图形面积_求高效的,计算两多边形重叠面积的算法,python实现
  5. linux 格式化 目录,Linux 磁盘分区、格式化、目录挂载
  6. c++ char* 改变长度重新赋值_[C/C++] 2 :分析下列代码有什么问题?
  7. amp 符号 php,php中引用符号(amp;)的使用详解_PHP教程
  8. C/C++小游戏 ——贪吃蛇
  9. python dicom图像分割_python读取DICOM头文件的实例
  10. 数据结构知识点总结_大牛带你学 | 考研数据结构中线性表中顺序结构的知识点总结...