InShot(com.camerasideas.instashot)图像编辑与滤镜渲染技术实现分析报告
反编译源码根目录:
/Users/ccc/Downloads/app/out/jadx_src/sources/(资源在.../resources/assets/、原生库在.../resources/lib/)。 代码经过混淆,jadx 用JADX INFO: compiled from: 原名.java保留了原始类名,下文"原名"即据此还原;所有路径省略公共前缀sources/。
1. 图像编辑主界面 ImageEditActivity:UI 组织与编辑状态管理
1.1 UI 组织(双视图架构:GL 渲染层 + 交互覆盖层)
com/camerasideas/instashot/ImageEditActivity.java(1441 行)继承 AbstractEditActivity(instashot/AbstractEditActivity.java),后者继承 X3/A.java = BaseMvpActivity(MVP 基类)。布局 R.layout.activity_image_edit 精简为两层:
<FrameLayout id=full_screen_fragment_container> <!-- 根,承载全屏 Fragment -->
<FrameLayout id=surfaceview_container>
<SurfaceView id=image_surfaceview/> <!-- GL 预览渲染面 -->
</FrameLayout>
<com.camerasideas.instashot.widget.ImageEditLayoutView id=edit_layout/>
<include .../fragment_collage_swap_title, full_screen_mask_layout, discard_image_works_layout/>
<com.camerasideas.instashot.widget.EditMenu id=edit_menu/>
</FrameLayout>
关键中间层 ImageEditLayoutView(widget/ImageEditLayoutView.java,extends LinearLayout,实现 GestureDetector.OnGestureListener, P8.d),构造时 inflate image_edit_layout_view.xml 并持有整个编辑器画布:
// ImageEditLayoutView.java:163-165
LayoutInflater.from(context).inflate(R.layout.image_edit_layout_view, this);
this.f32215f = (ItemView) findViewById(R.id.item_view); // 画布交互层
// 布局内另有 middle_layout(DragFrameLayout)、bottom_layout/bottom_parent_layout(Fragment 容器)、
// menu_dimmer、banner_container、view_spring_help
SurfaceView(image_surfaceview):由 GL 线程(GLGraphicsContext+GLThreadRenderer)渲染真实画面。ItemView(graphicproc/graphicsitems/ItemView.java,public class ItemView extends View implements A3.j, A3.h):透明覆盖层,负责选中框、边框、拖动/缩放手势、把触控分发给GraphicItemManager。
AbstractEditActivity 用 ButterKnife 绑定 20+ 控件(mItemView/mEditLayout/mMiddleLayout/mSurfaceView/mEditMenu/mBtnUndo/mBtnRedo/mBtnCompare/mBtnOpReset/mProgressBar/...),并持有 C3781h f24842t = C3781h.a(this)(GL 上下文)与 C1730i(图形项管理器);onCreate 中把 GL 表面与画布交给 Presenter:
// AbstractEditActivity.java:583-584
this.f24842t = C3781h.a(this);
((C3773e0) this.i).C1(this.mSurfaceView, this.mItemView);
1.2 编辑状态管理:MVP + 命令/备忘录撤销重做
MVP 三层:
- View 接口:
p108f6/InterfaceC3848l.java=IImageEditView(extendsp108f6/InterfaceC3837a.java=IBaseImageView),定义 60+ 回调(a()/Bc()/Dc()/P2()/Uc()/b9()/J4()/...)。 - Presenter:
p088e6/C3773e0.java,JADX INFO: compiled from: ImageEditPresenter.java,extends AbstractC3763b(BaseImagePresenter)→Y5/b.java(BaseEditPresenter)→Y5/c.java。Activity 内this.i即该 Presenter。 - 状态本体:Presenter 直接操作
C1730i.n()(GraphicItemManager 单例,Presenter 字段this.i)。
撤销/重做 = 命令 + 备忘录模式(p126g4/ 包):
p126g4/c.java=BackForward单例(经p126g4.c.k(context)获取),持有 4 个Stack<k>(照片/视频各一对 undo/redo 栈),并提供子栈切换(g()/h());d()/e()= canUndo/canRedo,b()/j()= undo/redo:
// BackForward.java — undo 栈操作
k kVarPop = this.f53204g.pop();
this.f53205h.push(kVarPop);
kVarLastElement = this.f53204g.lastElement();
...
lVar.b(kVar); // OpDataRollBack 执行回滚
this.f53207k.Mc(kVar); // 通知 OnBackForwardListener
T.a(new k1()); // EventBus 通知 UI 刷新
p126g4/k.java=OpData命令对象:int f53225a(操作类型)+EditInfo f53226b(状态快照)+ 时间戳,clone()深拷贝快照。- 快照即备忘录:
com/camerasideas/instashot/common/C1773e0.java=EditInfo,由p126g4/p.java=PhotoOpDataCreator对管理器内所有条目做深拷贝生成:
// PhotoOpDataCreator.a()
a10.f3161b = c1731j.clone(); // GridContainerItem 深拷贝
for (AbstractC1723b b : list) {
if (b instanceof V) arrayList2.add((V) b.R0()); // StickerItem/TextItem/PipItem 各自 clone()
}
- 回滚执行在
p126g4/l.java=OpDataRollBack;完成后经 EventBus(nj/k.java=org.greenrobot.eventbus.Subscribe注解)发p411v3.k1事件,ImageEditActivity.onEvent(k1)刷新 undo/redo 按钮(J4())。
菜单操作分发:ImageEditPresenter.d2(C4554d1) 是巨型 switch(操作码 21/24/36/38/41/65…),把 EditMenu(widget/EditMenu.java,FrameLayout + setEditType + OnEditClickListener)点击映射为具体编辑动作;Activity 只做薄壳:onClick → this.i.Y1()(保存)、V1()(重置/Fit)、z0()/F0()(撤销/重做)、d2(...)(菜单)。
设计模式:MVP(每个编辑功能 = Fragment + Presenter 对)、命令模式 + 备忘录(Gson 快照)、EventBus 事件驱动、观察者(p126g4/h.java OnBackForwardListener / p126g4/j.java OnStackChangeListener)、状态标志位(编辑类型 P0()、拼贴/画中画/滤镜模式 R0()/S0()/W0()/T0())。
Fragment 生命周期联动:ImageEditActivity.f 内部类实现 FragmentManager.m,在 Fragment 创建/销毁时控制菜单显隐。
2. com.camerasideas.graphicproc/(97 个类):自研图形处理框架
结论:这是 InShot 官方开源 "GraphicsDrawable" 架构的完整自研版——画布-条目模型:编辑器画布由若干可序列化、可变换的图形条目(BaseItem 体系)组成,条目各自绘制,管理器统一调度,GL 合成,草稿经 Gson 序列化。
2.1 entity/(14 类,全部可 Gson 序列化)
| 文件 | 原名 | 职责 |
|---|---|---|
a.java |
CaptionTextTemplate | 字幕模板 |
b.java |
CaptionsTextProperty | 字幕属性 |
c.java |
CaptionsTextProperty_Legacy | 兼容旧版字幕 |
d.java |
CompareProperty | 对比(原图/效果) |
e.java |
EdgeBlendProperty | 边缘融合 |
f.java |
EnhanceProperty | 画质增强 |
g.java |
TextBendEffect | 文字弯曲 |
h.java |
TextGlowEffect | 文字发光 |
i.java |
TextProperty | 文字属性 |
j.java |
TextProperty(kt) | 文字属性 Kotlin 版 |
k.java |
TextUnderlineEffect | 文字下划线 |
l.java |
TrackingInfo | 跟踪信息 |
m.java |
TrackingProperty | 跟踪属性 |
OutlineProperty.java |
OutlineProperty | 抠图蒙版 + 描边(f24039d=蒙版路径、f24042g=isAI、i=编辑版本计数、f24036a/b/c=描边样式/宽度/颜色;Parcelable + Gson OLP_*) |
所有字段带 @Jb.c("XX_xx") 注解——Jb/c.java 即 Gson SerializedName(重打包),这是草稿持久化的字段名稳定契约。
2.2 graphicsitems/(60 类,核心条目体系)
- 基类链:
com/camerasideas/graphics/entity/a.java=BaseClipInfo(id/时间戳/颜色,BCI_*键)→AbstractC1723b=BaseItem(extends BaseClipInfo,持有Matrix f24300z、变换数组f24278A/f24279B、关键帧Map<Long,I3.f> f24283F,BI_*键)→ 各具体条目。 - 条目类型:
| 混淆名 | 原名 | 职责 |
|---|---|---|
C1731j |
GridContainerItem | 拼贴容器(持有 GridImageItem 列表与布局) |
C1733l |
GridImageItem | 格内图片(滤镜/增强属性挂载点) |
AbstractC1743w |
ImageItem | 图片条目基类 |
V |
StickerItem | 贴纸/涂鸦结果 |
X |
TextItem | 文字 |
K |
PipItem | 画中画 |
C |
MosaicItem | 马赛克 |
C1722a |
AnimationItem | 动效条目(多帧) |
AbstractC1724c |
BorderItem | 边框 |
b0 |
WatermarkItem | 水印(总在顶层) |
N |
Placeholder | 占位 |
- 管理器:
C1730i=GraphicItemManager(DCL 单例n()),维护主绘制列表f24351b+ 4 个分类列表(Text/Image/Mosaic/Pip)+ 水印f24356g+ 容器f24357h:
// GraphicItemManager.b() — 按类型入分类列表
if (abstractC1723b instanceof X) this.f24352c.add(abstractC1723b);
else if (C1746z.i(...) || C1746z.b(...)) this.f24353d.add(abstractC1723b);
else if (abstractC1723b instanceof C) this.f24354e.add(abstractC1723b);
else if (abstractC1723b instanceof K) this.f24355f.add((K) abstractC1723b);
... // 水印始终沉底:list.remove(b0Var); list.add(this.f24356g);
C1729h 是它的回调适配器(实现 F3.D.a,把渲染完成回调转给 Presenter)。
- 渲染:
C1734m=GtrRenderer(单例)→C1740t=GtrRendererImpl,基于Oh/a.java=FrameBufferRenderer(把 GPUImage 滤镜对 FBO 执行 draw,支持 blend/scissor)把条目画进 GL 纹理;N3/包是配套的 GtrDrawable 体系(GtrDrawable/GtrImageDrawable/GtrDragDrawable/GtrButtonDrawable/ContainerDrawable)。ItemView 构造时挂接:
// ItemView.java:771
C1734m.f24393b.f24394a = new C1740t(context, new i());
- GL 生命周期:
p088e6/C3781h.java=GLGraphicsContext单例,内部用com/camerasideas/mvp/presenter/K0.java(GLThreadRenderer,自研 EGL 线程循环,非 GLSurfaceView)驱动 SurfaceView 渲染线程;同时持有 ItemView 引用。 - 触控/几何:
EnumC1727f=Direction、Z=TouchZone、Y=TouchTask、Q=RenderNode、P=RenderDragResponsiveArea、S/C1745y=ResizeDirectionStrategy、监听器接口族E(OnItemDraggedListener)/F(OnItemResizeDragListener)/G(OnItemSelectedListener)/H(OnItemViewActionChangedListener)/I(OnItemVisibilityListener)/J(OnItemZoneTouchListener)、T=SimpleItemResizeDragListener、U=SimpleItemViewActionListener、W=TextBounds、C1726e=ItemBounds、C1742v=ImageBounds、a0=TtsInfo、C1725d=CaptionInfo。
2.3 utils/(17 类)
| 文件 | 原名 | 职责 |
|---|---|---|
f.java |
DataSourceProvider | 泛型条目数据源(插入槽位搜索 b(Map,...)、变更通知) |
n.java |
ModelLoader | 异步模型下载(URL/md5 校验/进度回调,main Handler) |
c.java |
CutoutHelper | 抠图引擎门面(调 PortraitMatting) |
h.java |
EdgeBlendLayoutUtils | 边缘融合布局 |
i.java |
EmptyDataSourceProvider | 空数据源 |
j.java |
ItemAnimator | 条目动画 |
k.java |
ItemDrawContext | 给条目注入 FrameBufferRenderer/shader 表等 GL 访问器 |
l.java |
LayoutShuffleUtils | 拼贴布局打乱 |
q.java |
PortraitMattingModelLoaderFactory | 抠图模型加载工厂 |
r.java |
SimpleListChangedCallback | 列表变化回调 |
s.java |
TextItemKeyFrameHelper | 文字关键帧 |
t.java |
TrackingUtil | 跟踪工具 |
a.java |
AnimationProgressConverter | 动画进度转换 |
g.java |
DataSourceSupplementProvider | 数据补充接口 |
2.4 gson/(4 类)
MatrixTypeConverter、PaintTypeConverter(实现 Gson JsonSerializer/JsonDeserializer)、RectFTypeAdapter(Kotlin)、UriTypeConverter。注册点:E3/a.java = GsonBuilderFactory:
// E3/a.java:171 — 编辑器专用 Gson
new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriTypeConverter())
.registerTypeAdapter(RectF.class, new RectFTypeAdapter())
.registerTypeAdapter(Matrix.class, new MatrixTypeConverter())
.excludeFieldsWithModifiers(16, 128, 8)
.setExclusionStrategies(new i())
.registerTypeAdapter(C1731j.class, new h(context)) // 每个条目一个 InstanceCreator(带 Context 重建)
.registerTypeAdapter(C1733l.class, new g(context))
.registerTypeAdapter(X.class, new f(context))
.registerTypeAdapter(V.class, new e(context))
.registerTypeAdapter(K.class, new d(context))
.registerTypeAdapter(C1722a.class, new c(context))
.registerTypeAdapter(C.class, new b(context))
.registerTypeAdapter(b0.class, new C0032a(context))
.registerTypeAdapterFactory(new TextAttributesTypeAdapterFactory())
草稿落盘链路:p010a7/t.java = SaveDraftBuilder + p010a7/d.java = BaseWorkspace(抽象),由 BaseEditPresenter(Y5/b.java)在 H0()(退出编辑)时调用 tVar.b(dVar, c1773e0D0) 保存。
2.5 exception/(12 类)
防御性错误体系:BlackImageException(黑屏检测)、GLOutOfMemoryError、WrongFilterSizeException、CreateGifDecoderException、CreateGifBufferException、ResetItemRatioException、ItemIllegalStateException、RendererException、DrawTextLabelException、InfinityException、DebugPostException、AnimEngineException——渲染/导出失败被分类上报(T3/k.b/c 处理)。
3. 滤镜系统:GPUImage + GLSL 着色器 + LUT
3.1 GPUImage 框架(第三方移植 + 深度改造)
- 移植包
jp/co/cyberagent/android/gpuimage/(78 类):r.java=GPUImageFilter(基类:mGLProgId/mOutputFrameBuffer、onDraw(int tex, FloatBuffer, FloatBuffer)、runOnDraw(Runnable)命令队列、setFloat(loc,val))、S.java(extension 包)=GPUImageFilterGroup(嵌套组展开成链)、C.java=GPUImageRenderer(GLSurfaceView.Renderer + Camera.PreviewCallback)、M.java=GPUImageTwoInputFilter(第二输入纹理,setBitmap()→GLUtils.texImage2D上传)、N.java/C4105u=GPUImageTwoPassTextureSamplingFilter(双程模糊)、x0.java=PixelBuffer(离屏 EGL pbuffer 渲染到 Bitmap)、C4087b.java=GLProgramCache(ThreadLocal<Map<Class, GLProgram>>程序缓存)。 - 原生封装
GPUImageNativeLibrary.java:
static { System.loadLibrary("gpuimage-library"); System.loadLibrary("gpuimage-extension"); }
public static native void YUVtoARBG(byte[], int, int, int[]);
public static native byte[] aesDecrypt(Context, AssetManager, String); // 素材 AES 解密
public static native byte[] aesDecryptFile(Context, String);
public static native String getShader(Context, int key); // 原生 shader 缓存
3.2 滤镜链构建(Composite + 责任链/流水线)
编辑器顶层滤镜 = com/inshot/graphics/extension/Q.java = GPUImageEditorFilter extends GPUImageFilterGroup,由两条子链复合:
f(List<Nb.h>):调整/LUT 链 →C3582z.java=GPUFilterChainGroup;e(List<Nb.e>):特效链 →S(FilterGroup),特效由C3562u.java=GPUEffectFilter.createFilter(Context, Nb.e)工厂按效果名 switch + 反射实例化("com.inshot.graphics.extension.ai.emotion." + name家族:silkscreen/glow/doodle/flair/clone2/...)。
GPUImageFilterGroup.onDraw 用乒乓 FBO 串起整条链(每级从 Ph/b.java FrameBufferCache 取 FBO,输出纹理作为下一级输入)。离屏应用:I4/O.java = ImageFilterApplyer(用 PixelBuffer + GPUImageRenderer 逐滤镜渲染缩略图);实时预览经 C3/f.java = ImageFilterConverter(实现 a(inTex, outFbo))挂在 GridImageItem 的 ItemDrawContext 上,GLTextureView 变体用于 p088e6/C3787j(GLPipCropRenderer)。
3.3 LUT 滤镜实现(三套)
(1) 经典 2D LUT:com/inshot/graphics/extension/U.java = GPUImageLookupFilter extends GPUImageTwoInputFilter,内联标准 512×512 8×8 网格 fragment shader(blueColor*63.0 + mix(newColor1,newColor2,fract(blueColor)) + intensity uniform),纹理经 Ph/i.java(OpenGlUtils)glTexImage2D 上传,onDrawArraysPre 里 glUniform1f 设强度。
(2) AES 加密 LUT 资产:GPUFilterChainGroup.d()(C3582z.java)用原生解密后解码 PNG,并复用 p135gd/g.java(SoftReference Bitmap 缓存 + inBitmap):
byte[] bArrAesDecryptFile = C0659v.q(strZ)
? GPUImageNativeLibrary.aesDecryptFile(context, strZ)
: GPUImageNativeLibrary.aesDecrypt(context, context.getAssets(), strZ);
...
this.f47584c.setBitmap(bitmapDecodeByteArray, false); // 喂给 GPUImageLookupFilter
链式组装按 Nb/h.java(FilterProperty)条件追加:if (hVar.L()) { u10.f46653b = hVar.j(); arrayList.add(u10); }(LUT+强度)→ 锐化 GPUImageSharpenFilterV2 → GPUImageToolFilter → GPUMultiBandHsvFilter → GPUImageToneCurveFilterV2 → 自动调色。
(3) AI 自动调色 3 输入 LUT(GLES 3.0):U1/d.java = GPUBaseAdjustLookupFilter(顶点 shader 声明 4 组纹理坐标,uniform inputImageTexture2/3/4、w1..w3/intensity),两个子类:
U1/a.java=GPU3DLookupFilter:GLES3sampler3D,33³ 体纹理,AIAutoAdjust.load3DTexture(33,33,33,bytes);U1/b.java=GPUAdjustLookupFilter:2D 33 网格,AIAutoAdjust.load2DTexture(1089, 33, bytes)。
选择策略在 Pc/i.java = GPUImageAutoAdjustProxyFilter:
if (AIAutoAdjust.d(this.mContext)) // 设备 3D 纹理能力探测
this.f8760a = new U1.a(context, p129g7.a.f(context, "GPU3DLookupFilter.glsl"));
else
this.f8760a = new U1.b(context2, p129g7.a.f(context2, "GPUAdjustLookupFilter.glsl"));
this.f8760a.init();
两个 shader 均确认存在于 resources/assets/GPU3DLookupFilter.glsl(#version 300 es + #extension GL_OES_texture_3D + sampler3D + dimension=33.0)与 resources/assets/GPUAdjustLookupFilter.glsl(2D 33 网格 + uniform vec2 size)。LUT 权重/路径存于 Nb/c.java = AutoAdjustProperty(lutPaths f8040g size==3、w1..w3、intensity、autoAdjustSwitch),LUT 系数由原生 AIAutoAdjust.getLutCoefNative(经 GLPixelReader 读回)计算。LUT 的 .png 文件不随包,运行时下载/加密存储。
3.4 编辑器应用
fragment/image/ImageFilterFragment.java(mFilterGroupTab/mAdjustSeekBar/mFilterList)+ p088e6/C3829x0.java = ImageFilterPresenter;拖动滑块 → I4/N.java = FilterUtils 把索引映射到 FilterProperty 各 setter → ImageFilterPresenter.v1(...) 推送 AutoAdjustProperty → 实时重渲染。缩略图:adapter/imageadapter/ImageFilterAdapter.java 内 AsyncTask 共享 I4/O ImageFilterApplyer,FilterProperty.L() 用滤镜名充当 LUT id。
设计模式:Composite(FilterGroup 树 + EditorFilter 复合)、Factory(C3562u 特效工厂 + Pc/i LUT 代理)、责任链/流水线(乒乓 FBO)、命令队列(runOnDraw(Runnable) 在 GL 线程 onDrawFrame 排空)、缓存(GLProgramCache ThreadLocal + 原生 getShader + LookupBitmap SoftReference)、MVP + 可序列化参数对象(Nb/h FilterProperty / Nb/e EffectProperty,@Jb.c("FP_xx"))。
4. 图像处理库封装:libImageKit.so / libYXAImg.so
4.1 libImageKit.so(Skia 渲染引擎,纹理型 JNI)
com/inshot/graphics/engine/SkiaImageEngine.java 是唯一加载点,实现 Kc/a.java(Engine 接口):
static { System.loadLibrary("ImageKit"); }
private final long mNativeRenderer = nInit(); // native 句柄,构造即建
private native boolean nBindOutputTarget(long j10, int i, int i10, int i11); // FBO id
private native SkiaBaseLayer nCreateLayer(long j10, int i); // 1=border 2=image
private native void nDraw(long j10);
private native void nRelease(long j10);
private native void nSetClearColor(long j10, int i);
边界上不传 Bitmap——只传 long 指针、GL 纹理/FBO id、float[] 矩阵;Java 侧用 Ph/b.java = FrameBufferCache(LRU,key=w/h/format,ThreadLocal 单例,预算 min(512MB, heap/8))+ Ph/j = TextureFrameBuffer 管理 FBO,draw() 后恢复 GLES 状态。配套 layer/ 包(27 类):
SkiaBaseLayer/SkiaImageLayer/SkiaBorderLayer:JNI 句柄持有者(long mNativePtr+nSetEnable/nSetTexture/nSetTransformMatrix/...,SkiaImageLayer 有 11 个 native)。- 模板方法层体系:
n.java=ISLayer接口(a(enable)/b(param)/draw())、k.java=ISBaseLayer(参数→native 桥)、o.java=Layer(抽象 GL 层:持有Oh.aGPU 滤镜执行器,抽象a(Ph.j)->Ph.j纹理流水线)。 - 具体层:
a=BackgroundLayer、b=BlendLayer(GPUImage V 混合)、c=CanvasTexture(Bitmap→GL 纹理)、d=CropLayer、e=DrawableTexture、f/g=EdgeBlend、h=FilterLayer、i/j=FrameMask/FrameShape、p=LayoutLayer、r/s/t=Mask 系列、u=MattingLayer(抠图蒙版渲染)、v=PathCanvasLayer。
唯一消费方:layer/p.java = LayoutLayer,经 Kc/b.java = ISCompositingEngine(包装 SkiaImageEngine + 输出 Size + HashMap<Class, ISLayer>)用于拼贴/布局渲染。
4.2 libYXAImg.so + libYXAIEngine.so(CPU 算法,位图型 JNI)
9 个 com/android/** 算法类全部继承 com/android/algo/base/b.java = BaseLibrary,其 loadLibrary() 统一加载并带授权校验:
public void loadLibrary() {
...
libraries.add("MNN"); libraries.add("YXAIEngine"); libraries.add("YXAImg");
for (String lib : libraries) V8.c.a(this.mContext, lib); // ReLinker 加载
this.mLibLoaded = true;
}
消费方(这些直接传 Bitmap/byte[],并经 CerChecker(libcer.so)证书 + SHA1 校验后才 initNative(...),属商业授权 SDK 门面):
| 类 | 能力 | 关键 native |
|---|---|---|
com/android/inpaint/InPaint.java |
修复/去水印 | repairImageWithMaskNative(long,Bitmap,Bitmap,Bitmap),错误码 5376-5382 |
com/android/algo/caption/Caption.java |
字幕识别 | nativeDetect(long,Bitmap)->int[] |
com/android/algo/videoSeg/VidSeg.java |
视频分割 | nativeGetFrameMask(long,Bitmap,Bitmap,...) |
com/android/algo/vidSot/VidSot.java |
目标跟踪 | trackObjectNative(long,Bitmap)->float[] |
com/android/algo/autoAdjust/AIAutoAdjust.java |
自动调色 | get3DLutPixel, load2DTexture/load3DTexture(int,int,byte[]), lockBitmapPixels(Bitmap)->long |
com/android/videostabilize/VideoStabilize.java |
视频稳定 | nativeRenderSmooth(long,int×5,float[],float) |
com/android/audiosilencedt/AudioSilenceDt.java |
静音检测 | — |
com/android/autobeat/algo/AutoBeatAlgo.java |
自动卡点 | — |
消费门面:Yd/c.java→InPaint、p136ge/b.java→Caption、p182j4/h.java→VidSeg、G5/b.java→VidSot、Pc/g.java→AIAutoAdjust、p065d2/c.java→AutoBeatAlgo、p035bc/b.java/p257n2/c.java→VideoStabilize。
4.3 动态加载器三件套
V8/c.java= ReLinker:先System.loadLibrary,失败时从 APK zip 提取 .so 到context.getDir("lib",0)再System.load(HashSet 去重);另一调用方pl/droidsonroids/gif/GifInfoHandle。Q8/a.java= NativeLoader 单例(一次性设置 delegate):Eg/a.java(UtFileApiGuavaImpl,普通 System.load)与K5/a.java(AiBlendExploreMoreFactory,Facebook SoLoader 含恢复路径),服务于 Fresco 的native-filters/static-webp/native-imagetranscoder/native-imagetranscoder等。- 47 个 .so 确认存在于
resources/lib/{arm64-v8a,armeabi-v7a}/:含libImageKit.so、libYXAImg.so、libYXAIEngine.so、libMNN.so、libgpuimage-library.so、libgpuimage-extension.so、libisTurboJpeg.so、libskia.so、libcer.so、libportrait_matting_jni.so、libinpaint.so、libvid_seg.so、libcaption.so等。
设计模式:门面 over JNI(@Keep + long 句柄)、原生场景图 + Java 侧 GL 管线(per-thread LRU FBO 缓存)、模板方法层体系、单例加载器(ReLinker/NativeLoader)、两种 JNI 风格(GL id/指针型 vs Bitmap 型 + 授权校验)。
5. 人像分割/抠图:本地 MNN + 云端 PreciseCutout 双引擎
5.1 MNN 推理封装
com/android/algo/portraitmatting/PortraitMatting.java(@Keep,extends BaseLibrary):
private static native long initialize(Context c, String segModelPath, String mattingModelPath,
int segInputSize, int mattingInputSize, boolean needMatting, boolean lowPrecision,
String publicKey, String[] sha1, String pkg, String sign);
private static native void release(long handle);
private static native int run(long handle, Bitmap src, Bitmap mask /*ALPHA_8 输出*/, float ratioThresh);
getLibraries()="portrait_matting_jni";基类b.loadLibrary()追加"MNN"/"YXAIEngine"/"YXAImg"经 ReLinker(V8/c.java)加载;Contours.java直接loadLibrary("portrait_matting_jni")+loadLibrary("MNN")(ReLinker 兜底),并暴露原生getContours/getContoursAndApproxPoly/getMaskContours把蒙版转多边形。- Java 层没有 MNN 类(全树无 com.alibaba.mnn),纯 JNI;模型不进 assets,运行时下载:
graphicproc/utils/n.java=ModelLoader拉取https://inshot.cc/InShot/Model/PortraitModel_V1.1.0_20240929.zip(zip md534fb2fe5...+ 子文件 md5 校验),内含portrait_seg_v5.1.model+portrait_matting_v5.1.model+model.json;工厂utils/q.java=PortraitMattingModelLoaderFactory,路径解析在p088e6/V1.java=PortraitSegmentModelLoaderImpl。
5.2 管线与编辑器集成
graphicproc/utils/c.java=CutoutHelper(DCL 单例,持有 PortraitMatting + Contours):输入缩放至最长边 512(长宽比 ≥3.4 或 ≤0.294 用 320)→Bitmap.createBitmap(w,h,ALPHA_8)→synchronized{ f24460a.run(scaled, mask) }→ 转 ARGB_8888 拷贝。- 全流程
p156he/k.java=PortraitSegment(内部PortraitSegmentKit单例):Glide 解码 512×512 → 推理 → 蒙版 PNG 落盘或磁盘缓存(缓存名InstaShot_Cutout_Mask_<md5>.CutoutMask,经p307pe.j磁盘缓存读写)。 - 批量控制器
p088e6/U0.java=ImagePortraitSegment(clip 列表、AtomicInteger 进度、可取消p500zh.j任务),挂接在ImageEditPresenter(C3773e0)中(见M1(...)异步任务)。 - 云端路径
R4/e.java=AiMattingManager(Kotlin 协程,120s 超时,上传-执行-下载,状态ai_cutouting/ai_full_speed/uploading/downloading),参数R4/m.java(MattingParams,name="matting")。 - UI:
fragment/image/ImageCutoutFragment.java(iv_ai_cutout/iv_cutout/iv_paint/iv_outline/iv_apply)+p088e6/N.java=ImageCutoutPresenter(状态机 DEFAULT/BASIC/AI,双OutlineProperty快照f52189x/f52190y);手动精修ImageEraserFragment+p088e6/C3826w0.java=ImageEraserPresenter(paint 模式 1=erase/2=brush,尺寸/羽化 SeekBar,undo/redo,每笔CutoutHelper.b(ctx, bitmap, maskPath)),画笔引擎widget/ImageEraserControlView.java(GestureDetector +EraserBitmapComposer+EraserAdjustHelper+PortraitEraseData笔画)。 - 结果挂在条目
graphicproc/entity/OutlineProperty.f24039d(蒙版路径),应用逻辑在N.f1()(对比 OutlineProperty 版本号后切换条目可见性 + 上报apply_precise埋点);渲染由com/inshot/graphics/layer/u.java=MattingLayer(GPUImage)完成:
// 擦除: gl_FragColor = textureColor * textureColor2.a
// eraserType==1: textureColor*(0.65+textureColor2.a*0.35)
// 描边: gl_FragColor = texture2*(1.0-srcColor.a) + srcColor
- 视频剪辑:
p239m4/c.java=CutoutMaskBuilder+p182j4/o.java=ImageClipCutout(每帧 PortraitMatting)、p182j4/u.java=PipCutout(vidseg.yxm.modelsmall_256/middle_448,走 YX 引擎非 MNN)、p182j4/a.java=BaseCutout+instashot/cutout/CutoutTask.java(每帧成功/失败表)+p182j4/e.java=CutoutCache(2 线程 ShadowThreadPoolExecutor)。
设计模式:原生门面(BaseLibrary + @Keep + CerChecker 反篡改)、异步(RxJava Callable + Kotlin 协程 + 线程池 + AtomicInteger 进度)、监听器回调(InterfaceC3843g、R4/o 任务状态、n.d 模型下载)、DCL 单例、蒙版 = 文件路径 + 版本计数(缓存失效策略)。
6. 画笔/涂鸦/粒子/贴纸
6.1 涂鸦(策略 + 双缓冲 + 命令撤销)
com/camerasideas/instashot/widget/doodle/(18 文件):
| 文件 | 原名 | 职责 |
|---|---|---|
DoodleControlView.java |
DoodleControlView | 控制器(787 行:触控路由、双缓冲、undo/redo) |
i.java |
DoodleDrawDelegate | 笔迹委托(undo/redo 栈、重画) |
l.java |
IDoodle | 画笔策略接口 |
b.java |
BaseDoodle | 基础画笔(Path + PointF 记录) |
c.java |
BaseWithBitmapDoodle | 贴图画笔(沿路径盖章) |
j.java |
DoodleFactory | 画笔工厂 |
DoodleDrawView.java / DoodlePaintView.java |
— | 结果 ImageView / 笔刷光标预览 |
BaseDoodleDrawPathData.java |
— | 笔画数据(Parcelable + Gson) |
WriteDrawPathData/WaterDrawPathData/PlushDrawPathData.java |
— | 钢笔/水笔/荧光笔数据 |
a/d/k/n/o/p/q/r.java |
Arrow/Dash/Eraser/Neon/NormalLine/Plush/Water/Write | 8 种画笔策略 |
- 双缓冲:
Cf/C0654p.java=CanvasWrapper(Canvas + ARGB_8888 Bitmap):
public final void a() { this.f1429a.drawColor(0, PorterDuff.Mode.CLEAR); } // 清屏
public final void e(Path path, Paint paint) { this.f1429a.drawPath(path, paint); } // 画一笔
public final void h() { ... if (this.f1432d) { this.f1430b.recycle(); ... } } // 释放
DoodleControlView.j() 建 committed 层(f32777d)+ working 层(f32778e,拥有并回收 Bitmap),尺寸 = 裁剪区域。
- 笔画平滑(中点二次贝塞尔):
// BaseDoodle.A1()
this.f32755e.quadTo(x2, y2, (x2+x)/2f, (y2+y)/2f);
this.f32761l.add(new PointF(x, y));
c.e(this.f32755e, this.f32754d); // 画到 CanvasWrapper
Paint:STROKE + ROUND cap/join,宽度 dp((width/500dp)*strokeWidth/scale);橡皮 PorterDuffXfermode(PorterDuff.Mode.CLEAR) + alpha 0;Plush/Water 用 PathMeasure.getPosTan 沿线盖图章(间距 max(1,w/4)、随机旋转、SRC_ATOP 着色)。
- 撤销 = 命令:
DoodleDrawDelegate的 undo 栈f32780g/ redo 栈f32781h(元素BaseDoodleDrawPathData);重画 = 清屏后经DoodleFactory逐笔回放到 committed 层,再合成进 working 层,快照Bitmap.createBitmap(...)进DoodleDrawView.setDoodleBitmap();JSON 持久化到 SharedPreferences("doodlePreData"/"doodleNextData"),可跨进程存活。 - 确认:
ImageDoodleFragment(fragment/image/ImageDoodleFragment.java+ presenterp088e6/T.java)→Gj():取getDoodleBitmap()→ 自动裁边 → 存 PNG → 生成 graphicprocV(StickerItem)入编辑模型。数据模型entity/C1845g.java=DoodleInfo(type/width/color/alpha)。
6.2 粒子(纯 Canvas + ValueAnimator,无 GL)
widget/particle/ParticlesImageView.java(AppCompatImageView):onDraw→animator.c(canvas),每帧推进所有粒子(wVar.c())后postInvalidateOnAnimation()。M5/a.java=ParticleAnimator(extends ValueAnimator,时长=帧延迟,无限循环);M5/b.java=ParticleBitmapsFestivalFactory(decodeResourceStream 解码精灵,密度 480);N5/b.java= 抽象ParticleFactory.a(Rect) -> w[]。- 工厂:
N5/c.javaRibbleBottomParticleFactory、N5/d.javaRibbleDropParticleFactory、N5/e.javaRibbleTopParticleFactory;粒子M5/c/d/e(随机粉彩调色板 +PorterDuffColorFilter SRC_ATOP着色);基类I0/w.java(jadx 与 TopicsManager.kt 合并):abstract void c()物理步进(sin/cos 轨迹、Matrix 旋转缩放)、abstract void e(Canvas, Paint)=canvas.drawBitmap(bitmap, matrix, paint)。 - 用途:主题(
theme/ui/list/adapter/ParticleListAdapter.kt)、PRO 促销页(PromotionProFragment/SubscribeProFragment);setRibbleType(1|2)选择工厂。
6.3 贴纸
- 条目:
graphicproc/graphicsitems/V.java=StickerItem extends AbstractC1724c(BorderItem);L1(Uri)经F3/C.java=ItemStickerHelper加载:内存缓存p307pe.j→ 解码Cf/F.s(inSampleSize,750px 上限)或 assets(file:///android_asset/);显示缩放按 URI 命名约定选取(emoji_/sticker_/right_top_corner_mark/.sticker/.hotSticker);格式 PNG/GIF/WEBP(GIF 走 Tenor/Glide),动图 =C1722a.java=AnimationItem.L1(String, List<String>)多帧序列。 - 添加流程(
fragment/C2050m0.javaonItemClick):
V v10 = new V(contextWrapper);
v10.J0(rect.width()); v10.I0(rect.height()); v10.s1(z);
Uri uriA = M7.d.a(aVar.b(contextWrapper)); // path -> file Uri
if (uriA == null || !v10.L1(uriA)) return;
c1730i.a(v10); c1730i.e(); c1730i.J(v10); v10.f24320O = true; // 加入管理器+选中+弹入动画
- 数据模型
Ve/i.java=StickerModel.kt(id/stickerUrl/name/packageId/type/md5,Gson@Jb.c);UI 宿主fragment/StickerFragment.java+ 第三方com.shantanu.stickershop包 +GifStickerFragment/TenorGifStickerFragment。
7. 文字编辑与字体加载
7.1 字体加载(带缓存的双通道加载器)
Cf/m0.java = Typefaces(静态 Hashtable<String, Typeface> + 双重检查锁):
if (C0659v.q(str)) { // 是文件路径 → 先磁盘
typefaceCreateFromFile = Typeface.createFromFile(str); }
typefaceCreateFromAsset = Typeface.createFromAsset(context.getAssets(), str); // 否则 assets
f1425a.put(str, typeface); // 按名字缓存
assets 根目录确认 115 个文件,含 Roboto-Medium.ttf(默认)、Roboto-Regular/Thin/Condensed-Regular.ttf、AmaticSC-Regular.ttf、Lobster_1.3.otf、AngelFace.otf、BEBAS.ttf、PermanentMarker.ttf、Blackout-2am.ttf、BPdotsUnicase.otf、CaviarDreams.ttf、LuckiestGuy-Regular.ttf、danielbd.ttf、Aileron.otf 等;另有 res/font/roboto_medium_numbers.ttf;子目录 aniemoji01/ 存动效表情帧。字体数据模型 p165i5/e0.java = StoreFontBean(fontId/title/sourceURL/type;type=1 网络字体用 sourceURL,type=0 本地下载文件);ImageTextFontAdapter 预览经 Cf.m0.a(context, fontName);默认字体 KEY_TEXT_FONT 持久化于 B3/b.java = GraphicPreferences。
7.2 渲染栈(Java Spannable 模型 → 原生 JNI 排版引擎)
graphicproc/graphicsitems/X.java=TextItem:字段C1756j MeasuredTextInfo、a0 TtsInfo、C1725d CaptionInfo、com.camerasideas.graphics.text.p TextAttributes;Z1(String)设文本、X1(String)设字体 →L1()重测;S1()经S5/l.javaMaterialMeasuredText 测量。graphics/text/p.java=TextAttributes:Gson 可序列化属性袋(TAS_*键),内含span 数组:
| 字段 | 原名 | 效果 |
|---|---|---|
s |
TextColorSpan | 颜色 |
t |
TextCycleColorSpan | 循环变色 |
E |
TextStrokeSpan | 描边 |
v |
TextGlowSpan | 发光 |
z |
TextNeonSpan | 霓虹 |
A |
TextShadowSpan | 阴影 |
G |
TextUnderlineShadowSpan | 下划线+阴影 |
F |
TextUnderlineNeonSpan | 下划线+霓虹 |
H/I |
TextUnderlineSpan | 下划线 |
x |
TextLabelSpan | 标签 |
u |
TextFontSpan | 字体 |
- 原生桥:
S5/q.java=MaterialTextFactory把 TextItem 打包成Sb/n.java=TextInfo+Tb/k.java布局信息(T5/g.java=TextLayoutFactory,按 NONE/BEND/BEZIER_CURVE/HEART/FIT_IN_PATH 选择);测量:
// S5/l.java
LottieTextLayout l = layoutInfo.createLayout();
l.measure(contextD, nVarP, mA, jVar2); // org.instory.* JNI
org/instory/suit/textLayout/LottieDefaultTextLayout.java 是 JNI 文字引擎:@Keep private native long nInit(); nMeasure(long, AssetManager, TextInfo, List<LottieTextSpan>, LottieMeasureInfo); nRelease(long);变体 LottieBendTextLayout / LottieHeartTextLayout / LottieBezierCurveTextLayout / LottieTextFitInPathLayout。字号换算 graphics/text/C1753g.java = FontScaleResolver:baseFontSize * (canvasWidth/1080) * 9.642858 * scale;配套 graphics/text/ 包还有 ColorStyle/C1750d DropShadow/C1755i LinearGradientInfo/C1754h LabelImageInfo/C1756j MeasuredTextInfo/TextAttributesTypeAdapterFactory 等 30+ 类。
- UI:
fragment/image/ImageTextFragment.java(MyEditText + ViewPager 面板ImageTextFontPanel/ImageTextStylePanel/ImageTextTemplateFragment/TextAlignFragment,弹层ImageTextColor/Border/Label/Shadow/GlowFragment + ColorPickerFragment)+p088e6/C3810q1.java=ImageTextPresenter(g1()建 TextItem +N0(FontScaleResolver.b(xS))、m0()clone 还原、i1()提交持久化KEY_TEXT_FONT+ TextAttributes JSON)。
8. 图像导出:JPEG(TurboJPEG)/PNG,WebP 仅解码
8.1 JPEG 编码(libisTurboJpeg.so)
加载点 Bc/f.java = TJLoader:System.loadLibrary("isTurboJpeg")(带计时日志);JNI 桥 com/inshot/compressor/TJCompressor.java:
public static boolean a(String str, Bitmap bitmap, int i) { return nCompress(bitmap, i, str.getBytes()); }
public static boolean b(int i, int i10, Bitmap bitmap) { return nCompressFd(bitmap, i10, i); } // MediaStore fd
private static native boolean nCompress(Bitmap, int, byte[]);
private static native boolean nCompressFd(Bitmap, int, int);
private static native boolean nDecryptDecompress(Bitmap, byte[]);
private static native boolean nEncryptCompress(Bitmap, int, byte[]); // 加密导出变体
Bc/e.java = TJJpegCompressor:先把任意 config 归一为 ARGB_8888(API≥26 保留 ColorSpace)再交给 native;Bc/a.java = Compressor 抽象类即格式策略分发器:PNG 或广色域 ColorSpace → Bc/b.java = JavaCompressor(Bitmap.compress),否则 TurboJPEG(API≥29 优先 MediaStore openFileDescriptor("w") 的 fd 编码),native 失败再回退 Java,每步计时打日志。
8.2 WebP:仅解码
全树 grep 无导出级 WebP 编码器;G2/m.java = WebpDrawableEncoder 只是 Fresco 资源缓存层(把 drawable 的 ByteBuffer 写文件);libstatic-webp 由 Fresco com/facebook/imagepipeline/nativecode/c.java = StaticWebpNativeLoader 经 Q8.a.b("static-webp") 加载,com/bumptech/glide/integration/webp/(WebpBitmapFactory/WebpImage/WebpFrame/WebpHeaderParser)也是纯解码。图片导出 = JPEG 或 PNG。
8.3 完整保存管线(离屏 GL 渲染 → 黑屏检测 → 编码 → MediaStore)
- 触发:
ImageEditPresenter.Y1()→ 后台 executor(Eh.o+Lh.aIO 线程)→X9.accept()→IImageEditView.b9(path, paths)→ 启动ImageResultActivity。 - 参数构建:
instashot/save/c.java=ItemParamBuilder:qVar.f10717o = 90(JPEG 质量 90)、f10718p= SRGB、f10714l= PNG 标志(GridContainerItem.K1()背景透明时);T3/q.java=ItemParamInfo(序列化项目快照)。 - 渲染:
T3/k.java=ImageSaveImpl:GPUImage PixelBuffer(EGL pbuffer)离屏渲染,读回走GPUImageNativeLibrary.copyToBitmap:
x0Var = new x0(EGL10.EGL_NO_CONTEXT, w, h, colorSpace); // PixelBuffer 离屏
x0Var.c(b10); // renderer(T3/l ImageSaveRenderer 或 T3/B StitchSaveRenderer)
Bitmap bitmapB = x0Var.b(); // glReadPixels → Bitmap
if (bitmapB != null && this.f10685c.a(bitmapB) && !z10) return false; // BlackDetect
z11 = Bc.a.a(context2, bitmapB, path, srgbOrdinal, 90, isPng); // 编码
- 降级尺寸策略(策略模式):
T3/x.java=SaveImageSizeStrategy(抽象)→v.java=SaveCollageSizeStrategy(4096→320 阶梯,受 maxTextureSize 限制,API≤28 上限 3072)/z.java=SaveStitchSizeStrategy(16384→1024);由T3/n.java=ImageSaveTask(AsyncTask + BoosterShadowThreadPoolExecutor)逐个候选尺寸尝试,失败提示 "Try downgrading"。 - 黑屏检测
T3/C1050c.java=BlackDetect:降采样至 ~250px 读像素,全 0 →BlackImageException/GLOutOfMemoryError上报。 - Android 10+ 作用域存储:
Bc/a.b/c:is_pending=1插入 MediaStore(Pictures/inshot,_display_name=InShot_<ts>.jpg,mimeimage/jpeg|png,date_expires=+24h)→openFileDescriptor("w")原生 fd 编码 →Bc/a.d发布(is_pending=0);API<29 走临时文件路径 +Bc/g.java(TJUtil)删除。无 EXIF 处理(方向在 GPU 管线中烘焙)。 - 结果页:
ImageResultActivity+T3/m.java(监听器 post 主线程 Handler)+T3/i.java(ImageSaveEventListenerImpl),成功走a5(path)Glide 缩略图;分享辅助com/camerasideas/utils/W.javam()直接Bitmap.compress(PNG,100)写 MediaStore。
8.4 裁剪
com/camerasideas/crop/CropImageView.java:自定义 ImageView(裁剪框 Rect、手势、ValueAnimator + DecelerateInterpolator),输出归一化裁剪矩形(非 Bitmap):
bVar.f60393a = actualCropRect.left / this.f23977f.width(); // left 0..1
bVar.f60394b = actualCropRect.top / this.f23977f.height(); // top
bVar.f60395c = actualCropRect.right / this.f23977f.width(); // right
bVar.f60396d = actualCropRect.bottom / this.f23977f.height(); // bottom
p333r3/b.java=CropResult、Uc/c.java=CropProperty(left/top/right/bottom/aspect/presetIndex,h(w,h)→ RectF)——裁剪由渲染器在导出时应用,不产生中间 Bitmap;ImageCropFragment.java(fragment/image 包)+C2428h.javapresenter 存储 CropProperty。
9. 总体架构结论(设计模式清单)
- MVP + 事件总线:每个编辑功能 = Fragment(View 接口)+ Presenter(继承 BaseImagePresenter/BaseEditPresenter 链),Presenter 经
IImageEditView接口回调 UI,跨层通知走 GreenRobot EventBus(@nj.k= Subscribe)。 - 自研 "GraphicsDrawable" 画布模型(graphicproc 97 类):BaseItem 条目体系 + GraphicItemManager 单例 + GtrRenderer/GtrDrawable 合成 + Gson(@SerializedName 稳定键)草稿序列化 + 12 类渲染异常——与 InShot 开源 GraphicsDrawable 同构。
- 命令 + 备忘录撤销重做:BackForward 四栈 + OpData(EditInfo 深拷贝快照)+ OpDataRollBack 回滚 + 监听器/EventBus 通知。
- 复合/责任链:GPUImageFilterGroup 树 + ping-pong FBO 流水线;GPUImageEditorFilter = 调整链(GPUFilterChainGroup)+ 特效链。
- 工厂 + 策略:特效工厂(C3562u 反射)、3D/2D LUT 代理(Pc/i)、导出格式/尺寸策略(Bc/a、T3/x)、画笔工厂(DoodleFactory)、文字版式工厂(T5/g TextLayoutFactory)。
- 原生门面 + 句柄对象:SkiaImageEngine(long 句柄 + GL id)、BaseLibrary(Bitmap 型 JNI + CerChecker 授权)、ReLinker/NativeLoader 双加载器;重活(排版/抠图/马赛克/编解码)全部下沉 native(
org.instory.*、libImageKit.so、libYXAImg.so、libisTurboJpeg.so、libMNN.so)。 - 缓存/复用:GLProgramCache(ThreadLocal)、FrameBufferCache(LRU,per-thread)、Typefaces(Hashtable)、LookupBitmap(SoftReference + inBitmap)、贴图内存缓存 p307pe.j。
- 防御式错误处理:BlackImageException/GLOutOfMemoryError/WrongFilterSizeException 等分类异常 + 降级策略(native→Java 编码、尺寸阶梯)。
关键文件速查
| 主题 | 文件 |
|---|---|
| 编辑壳 | instashot/ImageEditActivity.java、instashot/AbstractEditActivity.java、instashot/widget/ImageEditLayoutView.java、instashot/widget/EditMenu.java |
| 状态/撤销 | p088e6/C3773e0.java(ImageEditPresenter)、Y5/b.java(BaseEditPresenter)、p126g4/c.java(BackForward)、p126g4/k.java(OpData)、p126g4/p.java(PhotoOpDataCreator)、instashot/common/C1773e0.java(EditInfo) |
| 画布框架 | graphicproc/graphicsitems/{ItemView,C1730i,AbstractC1723b,C1731j,C1733l,V,X,K,C,C1734m,C1740t}.java、com/camerasideas/graphics/entity/a.java(BaseClipInfo)、p088e6/C3781h.java(GLGraphicsContext)、Oh/a.java(FrameBufferRenderer)、N3/(GtrDrawable)、E3/a.java(GsonBuilderFactory) |
| 滤镜 | com/inshot/graphics/extension/{Q,S,U,C3582z,C3562u,K3}.java、U1/{a,b,d}.java、Pc/i.java、I4/{N,O}.java、fragment/image/ImageFilterFragment.java、p088e6/C3829x0.java(ImageFilterPresenter)、resources/assets/GPU3DLookupFilter.glsl、resources/assets/GPUAdjustLookupFilter.glsl |
| 原生库 | com/inshot/graphics/engine/SkiaImageEngine.java、com/inshot/graphics/layer/*.java、com/android/algo/base/b.java(BaseLibrary)、com/android/algo/portraitmatting/{PortraitMatting,Contours,PortraitMattingParam}.java、com/inshot/compressor/TJCompressor.java、V8/c.java(ReLinker)、Q8/a.java(NativeLoader) |
| 抠图 | graphicproc/utils/{c,q,n}.java、p156he/k.java(PortraitSegment)、p088e6/{N,U0,C3826w0}.java、R4/e.java(AiMattingManager)、fragment/image/{ImageCutoutFragment,ImageEraserFragment,ImageOutlineFragment}.java、graphicproc/entity/OutlineProperty.java、com/inshot/graphics/layer/u.java(MattingLayer) |
| 涂鸦/贴纸/文字 | instashot/widget/doodle/、instashot/widget/particle/、M5/、N5/、graphicproc/graphicsitems/V.java(StickerItem)、F3/C.java(ItemStickerHelper)、Cf/m0.java(Typefaces)、com/camerasideas/graphics/text/p.java(TextAttributes)、S5/{l,q}.java、T5/g.java、org/instory/suit/textLayout/*.java、fragment/image/ImageTextFragment.java、p088e6/C3810q1.java(ImageTextPresenter) |
| 导出 | T3/{k,n,l,B,x,v,z,C1050c,q}.java、instashot/save/c.java(ItemParamBuilder)、Bc/{a,b,e,f,g}.java、com/camerasideas/crop/CropImageView.java、instashot/ImageResultActivity.java、p333r3/b.java、Uc/c.java |