Gallery2源码阅读图片编辑
Gallery2源码阅读图片编辑
以下是从Gallery2的入口类FilterShowActivity (图片编辑功能)顺序的阅读,对看到的内容进行了一个简单的整理和记录。其中包括FilterShowActivity在创建时主要做的事情,界面的变换,历史记录的管理以及ProcessingService的功能。目前看到Gallery2的图片编辑基于renderscript实现,随后再做详细整理。
一,FilterShowActivity分析
@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//是否只显示竖屏boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait);if (onlyUsePortrait) {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);}clearGalleryBitmapPool();doBindService();getWindow().setBackgroundDrawable(new ColorDrawable(Color.GRAY));setContentView(R.layout.filtershow_splashscreen);}
在OnCreate()方法里面会做下面几件事,
- clearGalleryBitmapPool() 清理GalleryBitmapPool中缓存的图片
- doBindService() 绑定一个图片操作的数组
- setContentView(R.layout.filtershow_splashscreen) 进入图片编辑页面时有一个圆形进度条的闪屏页面
doBindService()主要是去bind ProcessingService,用于在service里面处理一些图片的操作
//bindService后的一些操作public void updateUIAfterServiceStarted() {MasterImage.setMaster(mMasterImage);ImageFilter.setActivityForMemoryToasts(this);mUserPresetsManager = new UserPresetsManager(this);mUserPresetsAdapter = new UserPresetsAdapter(this);setupMasterImage(); //处理MasterImage对象setupMenu(); //处理一些菜单 setDefaultValues(); //设置默认参数fillEditors(); //填充EditorgetWindow().setBackgroundDrawable(new ColorDrawable(0));loadXML(); //出现设置视图fillCategories(); //设置编辑种类loadMainPanel(); //加载底部的面板extractXMPData(); processIntent(); //处理具体的Intent 区分是选择图片 还是加载图片}
setupMasterImage()中主要做了一些MasterImage初始化的操作,比如设置HistoryManager,设置StateAdapter。
setupMenu()是初始化菜单,比如undoItem,redoItem,resetItem ,printItem。
fillEditors()主要是添加一些Editor,比如EditorGrad,EditorRedEye,EditorCrop等等。
loadXML()将闪屏视图替换为新的编辑视图
fillLooks(); //填充滤镜loadUserPresets(); //填充用户自定义fillBorders(); //填充边框fillTools(); //填充工具fillEffects(); //填充效果fillVersions(); //填充版本
fillCategories()是填充底部面板的一些操作。
loadMainPanel()就是用MainFragment替换底部的面板。
二,关于View的变换
整个图片显示都是基于自定义的ImageShow,和一开始想象的不太一样,以为图片编辑会用GLSurfaceView来显示,用OpenGl ES来做渲染,后来发现在编辑模块都是基于ImageShow,而这个控件是继承View。图片的滤镜等效果处理也是采用RenderScript,将处理好的图片通过ImageCache缓存起来,View只是负责单方面的显示。
ImageShow相关类的关系如下:
对于不同的滤镜或者特效处理,需要加载不同的Editor。
Editor
protected View mView; //topViewprotected ImageShow mImageShow; //展示Image的View
EditorCrop中
public EditorCrop() {super(ID);mChangesGeometry = true;}@Overridepublic void createEditor(Context context, FrameLayout frameLayout) {super.createEditor(context, frameLayout);if (mImageCrop == null) {mImageCrop = new ImageCrop(context);}mView = mImageShow = mImageCrop;mImageCrop.setEditor(this);}
在EditorCrop中mView和mImageShow会被替换成ImageCrop。
而在EditorPlaceHolder会根据Editor进行相关控件的隐藏和显示,
/*** Editor 容器类*/
public class EditorPlaceHolder {private static final String LOGTAG = "EditorPlaceHolder";private FilterShowActivity mActivity = null;private FrameLayout mContainer = null;private HashMap<Integer, Editor> mEditors = new HashMap<Integer, Editor>();private Vector<ImageShow> mOldViews = new Vector<ImageShow>();public EditorPlaceHolder(FilterShowActivity activity) {mActivity = activity;}public void setContainer(FrameLayout container) {mContainer = container;}public void addEditor(Editor c) {mEditors.put(c.getID(), c);}public boolean contains(int type) {if (mEditors.get(type) != null) {return true;}return false;}public Editor showEditor(int type) {Editor editor = mEditors.get(type);if (editor == null) {return null;}editor.createEditor(mActivity, mContainer);editor.getImageShow().attach();mContainer.setVisibility(View.VISIBLE);mContainer.removeAllViews();View eview = editor.getTopLevelView();ViewParent parent = eview.getParent();if (parent != null && parent instanceof FrameLayout) {((FrameLayout) parent).removeAllViews();}mContainer.addView(eview);hideOldViews();editor.setVisibility(View.VISIBLE);return editor;}public void setOldViews(Vector<ImageShow> views) {mOldViews = views;}public void hide() {mContainer.setVisibility(View.GONE);}public void hideOldViews() {for (View view : mOldViews) {view.setVisibility(View.GONE);}}public Editor getEditor(int editorId) {return mEditors.get(editorId);}
}
整个视图切换的流程就是需要不同的编辑效果,只需要替换不同的Editor,然后先移除ContainerView中的子view,隐藏oldViews,显示当前的editor即可。
三,HistoryManager
图片编辑中有一个撤销和恢复的操作,
private Vector<HistoryItem> mHistoryItems = new Vector<HistoryItem>(); //逆序排列
原理就是维护一个HistoryItem的Vector,不过这里记录是逆序排列的,也就是最近的记录是在最前面。
private void insert(HistoryItem preset, int position) {if (mCurrentPresetPosition != 0) {// in this case, let's discount the presets before the current one//这里进行判断,因为每次mCurrentPresetPosition之前的记录是无效的,所以需要舍弃掉。 有可能进行撤销操作了,之前的记录就不再需要了Vector<HistoryItem> oldItems = new Vector<HistoryItem>();for (int i = mCurrentPresetPosition; i < getCount(); i++) {oldItems.add(getItem(i));}clear();for (int i = 0; i < oldItems.size(); i++) {add(oldItems.elementAt(i));}mCurrentPresetPosition = position;notifyDataSetChanged();}mHistoryItems.insertElementAt(preset, position);mCurrentPresetPosition = position;notifyDataSetChanged();}
具体的撤销操作就是mCurrentPresetPosition指针加1,恢复就是减1。
public int redo() {mCurrentPresetPosition--;if (mCurrentPresetPosition < 0) {mCurrentPresetPosition = 0;}notifyDataSetChanged();updateMenuItems();return mCurrentPresetPosition;}public int undo() {mCurrentPresetPosition++;if (mCurrentPresetPosition >= getCount()) {mCurrentPresetPosition = getCount() - 1;}notifyDataSetChanged();updateMenuItems();return mCurrentPresetPosition;}
但是需要注意边界条件的控制。
具体的一个HistoryItem主要包含三个对象,
private ImagePreset mImagePreset;private FilterRepresentation mFilterRepresentation;private Bitmap mPreviewImage;
mImagePreset包含了一系列FilterRepresentation的叠加,维护了一个mFilterRepresentation的数组,也就是所有用过的效果参数保存起来,mFilterRepresentation就是当前效果的一些参数的保存。mPreviewImage好像没有用到。也就是说HistoryItem不保存具体的Bitamp对象,后面可以看到处理后的Bitmap缓存在BitmapCache里面。
四,ProcessingService
有这么几个重要的类
private ProcessingTaskController mProcessingTaskController; //装载任务的容器private ImageSavingTask mImageSavingTask; //保存图片 任务private UpdatePreviewTask mUpdatePreviewTask; //更新 预览图任务private HighresRenderingRequestTask mHighresRenderingRequestTask; //目前还没看到private FullresRenderingRequestTask mFullresRenderingRequestTask; //目前还没看到private RenderingRequestTask mRenderingRequestTask; //渲染任务
先简单标记一下,后面再细看。
Gallery2源码阅读图片编辑相关推荐
- 应用监控CAT之cat-client源码阅读(一)
CAT 由大众点评开发的,基于 Java 的实时应用监控平台,包括实时应用监控,业务监控.对于及时发现线上问题非常有用.(不知道大家有没有在用) 应用自然是最初级的,用完之后,还想了解下其背后的原理, ...
- centos下将vim配置为强大的源码阅读器
每日杂事缠身,让自己在不断得烦扰之后终于有了自己的清静时光来熟悉一下我的工具,每次熟悉源码都需要先在windows端改好,拖到linux端,再编译.出现问题,还得重新回到windows端,这个过程太耗 ...
- 源码阅读:AFNetworking(十六)——UIWebView+AFNetworking
该文章阅读的AFNetworking的版本为3.2.0. 这个分类提供了对请求周期进行控制的方法,包括进度监控.成功和失败的回调. 1.接口文件 1.1.属性 /**网络会话管理者对象*/ @prop ...
- 源码阅读:SDWebImage(六)——SDWebImageCoderHelper
该文章阅读的SDWebImage的版本为4.3.3. 这个类提供了四个方法,这四个方法可分为两类,一类是动图处理,一类是图像方向处理. 1.私有函数 先来看一下这个类里的两个函数 /**这个函数是计算 ...
- mybatis源码阅读
说下mybatis执行一个sql语句的流程 执行语句,事务等SqlSession都交给了excutor,excutor又委托给statementHandler SimpleExecutor:每执行一次 ...
- 24 UsageEnvironment使用环境抽象基类——Live555源码阅读(三)UsageEnvironment
24 UsageEnvironment使用环境抽象基类--Live555源码阅读(三)UsageEnvironment 24 UsageEnvironment使用环境抽象基类--Live555源码阅读 ...
- Transformers包tokenizer.encode()方法源码阅读笔记
Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode
- 源码阅读笔记 BiLSTM+CRF做NER任务 流程图
源码阅读笔记 BiLSTM+CRF做NER任务(二) 源码地址:https://github.com/ZhixiuYe/NER-pytorch 本篇正式进入源码的阅读,按照流程顺序,一一解剖. 一.流 ...
- 源码阅读:AFNetworking(八)——AFAutoPurgingImageCache
该文章阅读的AFNetworking的版本为3.2.0. AFAutoPurgingImageCache该类是用来管理内存中图片的缓存. 1.接口文件 1.1.AFImageCache协议 这个协议定 ...
最新文章
- ASP.NET MVC+Bootstrap个人博客之打造清新分页Helper(三)
- 新CCIE笔记之'口口相传'路由协议
- 基于哈希的图像检索 HABIR(HASHING BASELINE FOR IMAGE RETRIEVAL)
- 在地理文本处理技术上,高德有哪些技巧?
- java方面的文献综述怎么写_如何写文献综述?
- LeetCode 1926. 迷宫中离入口最近的出口(BFS)
- MSSQL数据批量插入优化详细
- 华为云回应“关闭私有云”传闻 将进行业务调整形成混合云产品部
- web测试内容及工具经典总结
- python中for循环和while循环的区别_Python中for循环语句和while循环语句有何不同
- 编写一个APPlet,再随机的位置上画出几个随机大小的矩形。
- vba判断文件编码格式_VBA编写Ribbon Custom UI编辑器07——写入xml
- js实现对树深度优先遍历与广度优先遍历
- 2019年全国大学生电子设计竞赛D题简易电路特性测试仪试题
- pandas抽样函数sample
- 经常有人会问,我的网站部署了好多个网站访问统计系统,比如百度、谷歌、CNZZ、JYC、51.la等等,但各个系统统计的结果总是不相同,而且差距不小,我该以哪个为准呢?
- Ubuntu 下安装VirtualBox主要步骤及出现的问题的解决方案
- 问题-ListView 使用的时候,已经遇到的问题;
- Niagara模块微信公众号连接
- python实现字符串类型 str 转换为 list 类型(unicode 转换为 list)
热门文章
- ppt转pdf转换器绿色版格式转换方法
- LED产品失效的技术分析指导
- qt生成pdf(用图片qgrabwidget抓取图片生成PDF;用文字生成pdf)
- LeetCode(多线程)- 1279. 红绿灯路口
- 关于新学期的计划(为了遇见更美好的自己)
- h5调用手机相机和录音机_奥林巴斯退出数码相机业务。打败你的不是同行,而是跨界!...
- Autoware学习笔记waypoint_follower之twist_filter
- Stanford UE4 UE5 C++ 开发 课程笔记(三)子弹物理碰撞与弹道校正
- 要学建筑学需要计算机基础吗,建筑学学什么 开设课程有哪些
- 空间三角形_对应三种空间形状的三种几何