Gallery2源码阅读图片编辑
来源:互联网 发布:代办淘宝商城 编辑:程序博客网 时间:2024/05/22 02:27
Gallery2源码阅读图片编辑
以下是从Gallery2的入口类FilterShowActivity (图片编辑功能)顺序的阅读,对看到的内容进行了一个简单的整理和记录。其中包括FilterShowActivity在创建时主要做的事情,界面的变换,历史记录的管理以及ProcessingService的功能。目前看到Gallery2的图片编辑基于renderscript实现,随后再做详细整理。
一,FilterShowActivity分析
@Override public 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(); //填充Editor getWindow().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; //topView protected ImageShow mImageShow; //展示Image的View
EditorCrop中
public EditorCrop() { super(ID); mChangesGeometry = true; } @Override public 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源码阅读图片编辑
- Gallery2图片编辑随笔
- android gallery2 源码分析
- Android Gallery2源码分析
- gallery2
- Android4.2中Gallery2源码移植
- Gallery2按地点查看图片的问题
- Android4.2.2 Gallery2源码分析(4)——GLCanvas.java
- Android4.2.2 Gallery2源码分析(5)——GLCanvasImpl.java
- Android4.2.2 Gallery2源码分析(6)——GLView.java
- Android4.2.2 Gallery2源码分析(4)——GLCanvas.java
- Android4.2.2 Gallery2源码分析(5)——GLCanvasImpl.java
- Android4.2.2 Gallery2源码分析(6)——GLView.java
- Camera保存的图片在Gallery2中找不到
- Gallery2 让图库不显示bmp格式图片
- Android平台Gallery2应用分析(七)---PhotoPage图片解码
- 图片编辑
- 图片编辑
- 第二周项目0-宣告“主权”
- 基于树莓派3的CAN总线编程
- 加减实现二分查找
- 最长递增子序列详解(longest increasing subsequence)(转)
- MongoDB——mongo-connector实例使用(for elasticsearch)
- Gallery2源码阅读图片编辑
- PHP时间参数列表
- LTR的理解
- android studio开发<三> 新建Activity界面,切换界面,滑动条控件
- ExecutorService 线程池使用和分析
- Dubbo视频教程《基于Dubbo的分布式系统架构视频教程》--课程列表
- C/C++ 多组输入计算a+b
- 第一周,项目0,宣誓主权
- Win10运行Linux的.sh文件