ImageKnife版本v1.0.0提交
Signed-off-by: zhoulisheng1 <zhoulisheng1@huawei.com>
This commit is contained in:
parent
7da838a541
commit
91d81d5210
|
@ -0,0 +1,17 @@
|
||||||
|
*.iml
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/caches
|
||||||
|
/.idea/libraries
|
||||||
|
/.idea/modules.xml
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/navEditor.xml
|
||||||
|
/.idea/assetWizardSettings.xml
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
||||||
|
.externalNativeBuild
|
||||||
|
/entry/.preview
|
||||||
|
.cxx
|
||||||
|
/node_modules
|
||||||
|
.idea
|
|
@ -0,0 +1,201 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
36
README.en.md
36
README.en.md
|
@ -1,36 +0,0 @@
|
||||||
# ImageKnife
|
|
||||||
|
|
||||||
#### Description
|
|
||||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
|
||||||
|
|
||||||
#### Software Architecture
|
|
||||||
Software architecture description
|
|
||||||
|
|
||||||
#### Installation
|
|
||||||
|
|
||||||
1. xxxx
|
|
||||||
2. xxxx
|
|
||||||
3. xxxx
|
|
||||||
|
|
||||||
#### Instructions
|
|
||||||
|
|
||||||
1. xxxx
|
|
||||||
2. xxxx
|
|
||||||
3. xxxx
|
|
||||||
|
|
||||||
#### Contribution
|
|
||||||
|
|
||||||
1. Fork the repository
|
|
||||||
2. Create Feat_xxx branch
|
|
||||||
3. Commit your code
|
|
||||||
4. Create Pull Request
|
|
||||||
|
|
||||||
|
|
||||||
#### Gitee Feature
|
|
||||||
|
|
||||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
|
||||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
|
||||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
|
||||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
|
||||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
|
||||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
|
306
README.md
306
README.md
|
@ -1,39 +1,291 @@
|
||||||
# ImageKnife
|
# GlideJS
|
||||||
|
|
||||||
#### 介绍
|
**专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单**
|
||||||
{**以下是 Gitee 平台说明,您可以替换此简介**
|
|
||||||
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
|
||||||
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
|
||||||
|
|
||||||
#### 软件架构
|
## 简介
|
||||||
软件架构说明
|
|
||||||
|
- 支持内存缓存,使用LRUCache算法,对图片数据进行内存缓存
|
||||||
|
- 支持磁盘缓存,对于下载图片会保存一份至磁盘当中。
|
||||||
|
- 支持进行图片变换。
|
||||||
|
- 支持用户配置参数使用:(例如:配置是否开启第一级内存缓存,配置磁盘缓存策略,配置仅使用缓存加载数据,配置图片变换效果,配置占位图,配置加载失败占位图等)。
|
||||||
|
- 推荐使用GlideImage组件配合GlideOption参数来实现功能
|
||||||
|
- 支持用户自定义配置实现能力参考GlideImage组件中对于入参GlideOption的处理
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
```
|
||||||
|
/entry/src/
|
||||||
|
- main/ets/default
|
||||||
|
- cache # 缓存相关内容
|
||||||
|
- diskstrategy # 缓存策略
|
||||||
|
- key # 缓存key生成策略
|
||||||
|
- Base64.ets # Base64算法
|
||||||
|
- CustomMap.ets # 自定义Map封装
|
||||||
|
- DiskCacheEntry.ets# 磁盘缓存entry
|
||||||
|
- DiskLruCache.ets # 磁盘LRU缓存策略
|
||||||
|
- FileReader.ets # 文件读取相关
|
||||||
|
- FileUtils.ets # 文件工具类
|
||||||
|
- LruCache.ets # 内存LRU缓存策略
|
||||||
|
- Md5.ets # MD5算法
|
||||||
|
|
||||||
|
- glide # glide主要内容
|
||||||
|
- compress # 压缩相关
|
||||||
|
- constants # 常量相关
|
||||||
|
- entry # 部分数据结构
|
||||||
|
- holder # 占位图相关解析
|
||||||
|
- interface # 接口相关
|
||||||
|
- networkmanage # 网络相关
|
||||||
|
- pngj # pngj相关
|
||||||
|
- requestmanage # Glide请求相关
|
||||||
|
- resourcemanage # 本地资源解析相关
|
||||||
|
- transform # 图片变换相关
|
||||||
|
- utils # 工具类相关
|
||||||
|
- Glide.ets # Glide门面,app持久化类
|
||||||
|
- GlideData.ets # 数据封装
|
||||||
|
- GlideImage.ets # 自定义控件封装
|
||||||
|
- GlideOption.ets # 用户传参数封装
|
||||||
|
- PixelMapPack.ets # PixelMap封装
|
||||||
|
- RequestOption.ets # 用户设置参数封装
|
||||||
|
|
||||||
|
- pages # 测试page页面列表
|
||||||
|
- basicTestFeatureAbilityPage.ets # 测试元能力
|
||||||
|
- basicTestFileIOPage.ets # 测试fileio
|
||||||
|
- basicTestMediaImage.ets # 测试媒体image
|
||||||
|
- basicTestResourceManagerPage.ets # 测试本地资源解析
|
||||||
|
- CompressPage.ets # 压缩页面
|
||||||
|
- frescoImageTestCasePage.ets # 测试属性动画组件切换
|
||||||
|
- frescoLayerTestCasePage.ets # 测试GlideImage组件切换配合属性动画
|
||||||
|
- frescoRetryTestCasePage.ets # 测试GlideImage加载失败重试
|
||||||
|
- index.ets # 测试页面入口
|
||||||
|
- indexFresco.ets # 二级测试页面入口
|
||||||
|
- loadNetworkTestCasePage.ets # 网络加载测试
|
||||||
|
- loadResourceTestCasePage.ets # 本地加载测试
|
||||||
|
- showErrorholderTestCasePage.ets # 加载失败占位图测试
|
||||||
|
- storageTestDiskLruCache.ets # 磁盘缓存测试
|
||||||
|
- storageTestLruCache.ets # 内存缓存测试
|
||||||
|
- testAllCacheInfoPage.ets # 所有缓存信息获取测试
|
||||||
|
- testAllTypeGlideImagePage.ets # 所有类型图片加载测试
|
||||||
|
- testAllTypeNativeImagePage.ets # 所有类型本地图片加载测试
|
||||||
|
- testGifDontAnimatePage.ets # gif加载静态图片测试
|
||||||
|
- testGlideOptionChangedPage.ets # GlideOption数据切换测试
|
||||||
|
- testGlideOptionChangedPage2.ets # GlideOption数据切换测试
|
||||||
|
- testMultiThreadWorkerPage2.ets # 多线程测试
|
||||||
|
- testPlaceholderPage.ets # 加载占位图测试
|
||||||
|
- testPreloadPage.ets # 预加载测试
|
||||||
|
- testResourceManagerPage.ets # 解析本地资源测试
|
||||||
|
- TransformPixelMapPage.ets # 所有类型变换测试
|
||||||
|
- transformTestCasePage.ets # 所有类型变换配合GlideImage测试
|
||||||
|
|
||||||
|
- workers # 测试worker多线程
|
||||||
|
- worker1.js # worker多线程测试
|
||||||
|
```
|
||||||
|
|
||||||
|
## 接口说明
|
||||||
|
|
||||||
|
### RequestOpton 用户配置参数
|
||||||
|
|
||||||
|
| 方法名 | 入参 | 接口描述 |
|
||||||
|
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||||
|
| load(src: string \| PixelMap \| Resource) | string \| PixelMap \| Resource | 待加载图片的资源 |
|
||||||
|
| setImageViewSize(imageSize: { width: number, height: number }) | { width: number, height: number } | 传入显示图片组件的大小,变换的时候需要作为参考 |
|
||||||
|
| diskCacheStrategy(strategy: DiskStrategy) | DiskStrategy | 配置磁盘缓存策略 NONE SOURCE RESULT ALL AUTOMATIC |
|
||||||
|
| placeholder(src: PixelMap \| Resource, func?: AsyncSuccess<PixelMap>) | src: PixelMap \| Resource, func?: AsyncSuccess<PixelMap> | 配置占位图,其中func为数据回调函数 |
|
||||||
|
| errorholder(src: PixelMap \| Resource, func?: AsyncSuccess<PixelMap>) | src: PixelMap \| Resource, func?: AsyncSuccess<PixelMap> | 配置加载失败占位图,其中func为数据回调函数 |
|
||||||
|
| addListener(func: AsyncCallback<PixelMap>) | func: AsyncCallback<PixelMap> | 配置整个监听回调,数据正常加载返回,加载失败返回错误信息 |
|
||||||
|
| thumbnail(sizeMultiplier:number, func?: AsyncSuccess<GlideData>) | sizeMultiplier:number, func?: AsyncSuccess<GlideData> | 设置缩略图比例,缩略图返回后,加载并展示缩略图 |
|
||||||
|
| addProgressListener(func?: AsyncSuccess<string>){ this.progressFunc = func; return this; } | func?: AsyncSuccess<string> | 设置网络下载百分比监听,返回数据加载百分比数值 |
|
||||||
|
| addRetryListener(func?: AsyncSuccess<any>){ this.retryFunc = func; return this; } | func?: AsyncSuccess<any> | 设置重试监听 |
|
||||||
|
| addAllCacheInfoCallback(func: IAllCacheInfoCallback) | func: IAllCacheInfoCallback | 设置获取所有缓存信息监听 |
|
||||||
|
| skipMemoryCache(skip: boolean) | skip: boolean | 配置是否跳过内存缓存 |
|
||||||
|
| retrieveDataFromCache(flag: boolean) | flag: boolean | 配置仅从缓存中加载数据 |
|
||||||
|
| transform(transform: BaseTransform<PixelMap>) | transform: BaseTransform<PixelMap> | 配置自定义变换类型 |
|
||||||
|
| centerCrop(fd: number, out_width: number, out_height: number, callback?: AsyncTransform<Promise<PixelMap>>) | fd: number, out_width: number, out_height: number, callback?: AsyncTransform<Promise<PixelMap>> | 静态方法可以根据图片文件,目标显示大小,进行对应centerCrop |
|
||||||
|
| rotateImage(fd: number, degreesToRotate: number) | fd: number, degreesToRotate: number | 静态方法可以根据图片文件,和旋转角度,进行对应rotateImaroge |
|
||||||
|
| centerInside(fd: number, out_width: number, out_height: number, callback?: AsyncTransform<Promise<PixelMap>>) | fd: number, out_width: number, out_height: number, callback?: AsyncTransform<Promise<PixelMap>> | 静态方法可以根据图片文件,目标显示大小,进行对应centerInside |
|
||||||
|
| fitCenter(fd: number, out_width: number, out_height: number , callback?: AsyncTransform<Promise<PixelMap>>) | fd: number, out_width: number, out_height: number , callback?: AsyncTransform<Promise<PixelMap>> | 静态方法可以根据图片文件,目标显示大小,进行对应fitCenter |
|
||||||
|
|
||||||
|
### Glide 启动器/门面类
|
||||||
|
|
||||||
|
| 方法名 | 入参 | 接口描述 |
|
||||||
|
| ------------------------------- | ---------------------- | ---------------------------------- |
|
||||||
|
| call(request: RequestOption) | request: RequestOption | 根据用户配置参数具体执行加载流程 |
|
||||||
|
| preload(request: RequestOption) | request: RequestOption | 根据用户配置参数具体执行预加载流程 |
|
||||||
|
|
||||||
|
### 缓存策略相关
|
||||||
|
|
||||||
|
| 使用方法 | 类型 | 策略描述 |
|
||||||
|
| ------------------------------------------ | --------- | ---------------------------------------- |
|
||||||
|
| request.diskCacheStrategy(new ALL()) | ALL | 表示既缓存原始图片,也缓存转换过后的图片 |
|
||||||
|
| request.diskCacheStrategy(new AUTOMATIC()) | AUTOMATIC | 表示尝试对本地和远程图片使用最佳的策略 |
|
||||||
|
| request.diskCacheStrategy(new DATA()) | DATA | 表示只缓存原始图片 |
|
||||||
|
| request.diskCacheStrategy(new NONE()) | NONE | 表示不缓存任何内容 |
|
||||||
|
| request.diskCacheStrategy(new RESOURCE()) | RESOURCE | 表示只缓存转换过后的图片 |
|
||||||
|
|
||||||
|
### 图片变换相关
|
||||||
|
|
||||||
|
| 使用方法 | 类型 | 相关描述 |
|
||||||
|
| ------------------------------------------------------------ | ---------------------------------- | -------------- |
|
||||||
|
| request.transforms(new BlurTransformation()) | BlurTransformation | 模糊处理 |
|
||||||
|
| request.transforms(new BrightnessFilterTransformation()) | BrightnessFilterTransformation | 亮度滤波器 |
|
||||||
|
| request.transforms(new ContrastFilterTransformation()) | ContrastFilterTransformation | 对比度滤波器 |
|
||||||
|
| request.transforms(new CropCircleTransformation()) | CropCircleTransformation | 圆形剪裁显示 |
|
||||||
|
| request.transforms(new CropCircleWithBorderTransformation()) | CropCircleWithBorderTransformation | 圆环展示 |
|
||||||
|
| request.transforms(new CropSquareTransformation()) | CropSquareTransformation | 正方形剪裁 |
|
||||||
|
| request.transforms(new CropTransformation()) | CropTransformation | 自定义矩形剪裁 |
|
||||||
|
| request.transforms(new GrayscaleTransformation()) | GrayscaleTransformation | 灰度级转换 |
|
||||||
|
| request.transforms(new InvertFilterTransformation()) | InvertFilterTransformation | 反转滤波器 |
|
||||||
|
| request.transforms(new PixelationFilterTransformation()) | PixelationFilterTransformation | 像素化滤波器 |
|
||||||
|
| request.transforms(new RotateImageTransformation()) | RotateImageTransformation | 图片旋转 |
|
||||||
|
| request.transforms(new RoundedCornersTransformation()) | RoundedCornersTransformation | 圆角剪裁 |
|
||||||
|
| request.transforms(new SepiaFilterTransformation()) | SepiaFilterTransformation | 乌墨色滤波器 |
|
||||||
|
| request.transforms(new SketchFilterTransformation()) | SketchFilterTransformation | 素描滤波器 |
|
||||||
|
|
||||||
|
|
||||||
#### 安装教程
|
|
||||||
|
|
||||||
1. xxxx
|
## 代码示例
|
||||||
2. xxxx
|
|
||||||
3. xxxx
|
|
||||||
|
|
||||||
#### 使用说明
|
1.首先初始化全局Glide实例,在app.ets中调用Glide.with()进行初始化
|
||||||
|
|
||||||
1. xxxx
|
```
|
||||||
2. xxxx
|
import {Glide} from './glide/Glide.ets'
|
||||||
3. xxxx
|
export default {
|
||||||
|
data: {
|
||||||
|
glide: {} // Glide全局占位符
|
||||||
|
},
|
||||||
|
onCreate() {
|
||||||
|
this.data.glide = Glide.with();// Glide占位符全局初始化赋值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### 参与贡献
|
2.在页面index.ets中使用Glide
|
||||||
|
|
||||||
1. Fork 本仓库
|
```
|
||||||
2. 新建 Feat_xxx 分支
|
@Entry
|
||||||
3. 提交代码
|
@Component
|
||||||
4. 新建 Pull Request
|
struct Index {
|
||||||
|
build() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面初始化完成,生命周期回调函数中 进行调用Glide
|
||||||
|
aboutToAppear() {
|
||||||
|
let requestOption = new RequestOption();
|
||||||
|
requestOptin.load($r('app.media.IceCream'))
|
||||||
|
.addListener((err,data) => {
|
||||||
|
//加载成功/失败回调监听
|
||||||
|
})
|
||||||
|
...
|
||||||
|
Glide.call(requestOption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var Glide;
|
||||||
|
var defaultTemp = globalThis.exports.default
|
||||||
|
if (defaultTemp != undefined) {
|
||||||
|
Glide = defaultTemp.data.glide;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
#### 特技
|
|
||||||
|
|
||||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
#### 推荐使用:
|
||||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
|
||||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
使用GlideOption作为入参,配合自定义组件GlideImage使用。
|
||||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
|
||||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
```typescript
|
||||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct Index {
|
||||||
|
@State glideOption1: GlideOption =
|
||||||
|
{
|
||||||
|
loadSrc: "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83ericA1Mv66TwicuYOtbDMBcUhv1aa9RJBeAn9uURfcZD0AUGrJebAn1g2AjN0vb2E1XTET7fTuLBNmA/132",
|
||||||
|
size: { width: 300, height: 300 },
|
||||||
|
placeholderSrc: $r('app.media.icon_loading'),
|
||||||
|
errorholderSrc: $r('app.media.icon_failed'),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Scroll() {
|
||||||
|
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||||
|
GlideImage({ glideOption: $glideOption1 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 自定义实现:
|
||||||
|
|
||||||
|
使用原生Image组件,配合用户配置参数实现。
|
||||||
|
|
||||||
|
##### 步骤1:
|
||||||
|
|
||||||
|
定义一个入参 PixelMap
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@State tomatoPixelMap:PixelMap = new PixelMap();
|
||||||
|
width:number = 200;
|
||||||
|
height:number = 200;
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 步骤2:
|
||||||
|
|
||||||
|
在你的component组件中,写下一个Image组件,将基础参数(入参PixelMap,组件的宽、高)配置好
|
||||||
|
|
||||||
|
```
|
||||||
|
Image(this.tomatoPixelMap)
|
||||||
|
.backgroundColor(Color.Grey)
|
||||||
|
.objectFit(ImageFit.Contain)
|
||||||
|
.width(this.width)
|
||||||
|
.height(this.height)
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 步骤3:
|
||||||
|
|
||||||
|
在aboutToAppear() 函数中调用加载流程
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
//配置参数
|
||||||
|
let requestOptin = new RequestOption();
|
||||||
|
//加载本地图片
|
||||||
|
requestOptin.load($r('app.media.IceCream'))
|
||||||
|
.addListener((err,data) => {
|
||||||
|
//加载成功/失败回调监听
|
||||||
|
})
|
||||||
|
.placeholder( $r('app.media.icon_loading'), (data)=>{
|
||||||
|
// 占位图回调监听
|
||||||
|
})
|
||||||
|
.errorholder(this.glideOption.errorholderSrc, (data)=>{
|
||||||
|
// 失败占位图回调监听
|
||||||
|
})
|
||||||
|
.thumbnail(this.glideOption.thumbSizeMultiplier, (data) => {
|
||||||
|
// 缩略图加载成功回调
|
||||||
|
})
|
||||||
|
// 一定要把控件大小传给RequestOption,图片变换必须
|
||||||
|
.setImageViewSize({width:this.width, height:this.height})
|
||||||
|
// 设置缓存策略
|
||||||
|
.diskCacheStrategy(new Strategy())
|
||||||
|
.addProgressListener((percentValue: string) => {
|
||||||
|
// 图片网络加载进度条百分比回调
|
||||||
|
})
|
||||||
|
.addRetryListener((error: any) => {
|
||||||
|
// 加载失败重试监听 图片加载失败时优先展示重试图层,点击重试图层,会重新进行一次加载流程
|
||||||
|
})
|
||||||
|
.transforms(new RoundedCornersTransformation({top:10}))
|
||||||
|
// 启动加载流程,执行结果将会返回到上面的回调接口中
|
||||||
|
Glide.call(requestOptin);
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 步骤4:
|
||||||
|
|
||||||
|
更多细节设置请参考自定义Component的GlideImage实现
|
||||||
|
|
||||||
|
## 演示
|
||||||
|
|
||||||
|
<img src="screenshot/g3.gif" width="50%"/>
|
||||||
|
|
||||||
|
<img src="screenshot/g1.gif" width="50%"/><img src="screenshot/g2.gif" width="50%"/>
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
apply plugin: 'com.huawei.ohos.app'
|
||||||
|
|
||||||
|
//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
|
||||||
|
ohos {
|
||||||
|
compileSdkVersion 8
|
||||||
|
supportSystem "standard"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'https://repo.huaweicloud.com/repository/maven/'
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://developer.huawei.com/repo/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.huawei.ohos:hap:3.0.5.2'
|
||||||
|
classpath 'com.huawei.ohos:decctest:1.2.7.2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'https://repo.huaweicloud.com/repository/maven/'
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://developer.huawei.com/repo/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
/build
|
||||||
|
/node_modules
|
|
@ -0,0 +1,21 @@
|
||||||
|
apply plugin: 'com.huawei.ohos.hap'
|
||||||
|
//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
|
||||||
|
ohos {
|
||||||
|
compileSdkVersion 8
|
||||||
|
defaultConfig {
|
||||||
|
compatibleSdkVersion 8
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
proguardOpt {
|
||||||
|
proguardEnabled false
|
||||||
|
rulesFiles 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
|
||||||
|
testImplementation 'junit:junit:4.13.1'
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
# config module specific ProGuard rules here.
|
|
@ -0,0 +1,144 @@
|
||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"bundleName": "com.huawei.mydemoall",
|
||||||
|
"vendor": "huawei",
|
||||||
|
"version": {
|
||||||
|
"code": 1000000,
|
||||||
|
"name": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deviceConfig": {
|
||||||
|
"default": {
|
||||||
|
"network": {
|
||||||
|
"cleartextTraffic": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"package": "com.bumptech.glidejs_ohos",
|
||||||
|
"name": ".MyApplication",
|
||||||
|
"mainAbility": ".MainAbility",
|
||||||
|
"srcPath": "",
|
||||||
|
"deviceType": [
|
||||||
|
"phone",
|
||||||
|
"tablet",
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"distro": {
|
||||||
|
"deliveryWithInstall": true,
|
||||||
|
"moduleName": "entry",
|
||||||
|
"moduleType": "entry",
|
||||||
|
"installationFree": false
|
||||||
|
},
|
||||||
|
"abilities": [
|
||||||
|
{
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"entities": [
|
||||||
|
"entity.system.home"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"action.system.home"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"orientation": "unspecified",
|
||||||
|
"visible": true,
|
||||||
|
"srcPath": "MainAbility",
|
||||||
|
"name": ".MainAbility",
|
||||||
|
"srcLanguage": "ets",
|
||||||
|
"icon": "$media:icon",
|
||||||
|
"description": "$string:mainability_description",
|
||||||
|
"formsEnabled": false,
|
||||||
|
"label": "$string:GlideJS_OHOS",
|
||||||
|
"type": "page",
|
||||||
|
"launchType": "standard"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reqPermissions": [
|
||||||
|
{
|
||||||
|
"name": "ohos.permission.READ_USER_STORAGE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ohos.permission.INTERNET",
|
||||||
|
"reason": "Api call",
|
||||||
|
"usedScene": {
|
||||||
|
"ability": [
|
||||||
|
"com.zls.glidejscache.MainAbility"
|
||||||
|
],
|
||||||
|
"when": "always"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ohos.permission.READ_MEDIA",
|
||||||
|
"reason": "location background",
|
||||||
|
"usedScene": {
|
||||||
|
"when": "always",
|
||||||
|
"ability": [
|
||||||
|
"com.zls.glidejscache.MainAbility"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ohos.permission.WRITE_MEDIA",
|
||||||
|
"reason": "location background",
|
||||||
|
"usedScene": {
|
||||||
|
"when": "always",
|
||||||
|
"ability": [
|
||||||
|
"com.zls.glidejscache.MainAbility"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
{
|
||||||
|
"mode": {
|
||||||
|
"syntax": "ets",
|
||||||
|
"type": "pageAbility"
|
||||||
|
},
|
||||||
|
"pages": [
|
||||||
|
"pages/index",
|
||||||
|
"pages/indexFresco",
|
||||||
|
"pages/frescoLayerTestCasePage",
|
||||||
|
"pages/frescoImageTestCasePage",
|
||||||
|
"pages/frescoRetryTestCasePage",
|
||||||
|
"pages/basicTestFeatureAbilityPage",
|
||||||
|
"pages/basicTestFileIOPage",
|
||||||
|
"pages/basicTestMediaImage",
|
||||||
|
"pages/basicTestResourceManagerPage",
|
||||||
|
"pages/storageTestLruCache",
|
||||||
|
"pages/storageTestDiskLruCache",
|
||||||
|
"pages/testMemoryCachePage",
|
||||||
|
"pages/transformTestCasePage",
|
||||||
|
"pages/pngjTestCasePage",
|
||||||
|
"pages/testAllTypeGlideImagePage",
|
||||||
|
"pages/testAllTypeNativeImagePage",
|
||||||
|
"pages/loadResourceTestCasePage",
|
||||||
|
"pages/loadNetworkTestCasePage",
|
||||||
|
"pages/showErrorholderTestCasePage",
|
||||||
|
"pages/TransformPixelMapPage",
|
||||||
|
"pages/testGifDontAnimatePage",
|
||||||
|
"pages/testPreloadPage",
|
||||||
|
"pages/testGlideOptionChangedPage",
|
||||||
|
"pages/testGlideOptionChangedPage2",
|
||||||
|
"pages/CompressPage",
|
||||||
|
"pages/testAllCacheInfoPage",
|
||||||
|
"pages/testResourceManagerPage",
|
||||||
|
"pages/testMultiThreadWorkerPage2",
|
||||||
|
"pages/testGlideOptionChangedPage",
|
||||||
|
"pages/CropImagePage",
|
||||||
|
"pages/networkTestCasePage",
|
||||||
|
"pages/jpegProgressTestCasePage"
|
||||||
|
],
|
||||||
|
"name": ".MainAbility",
|
||||||
|
"window": {
|
||||||
|
"designWidth": 720,
|
||||||
|
"autoDesignWidth": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import app from '@system.app';
|
||||||
|
|
||||||
|
import {Glide} from './glide/Glide.ets'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data: {
|
||||||
|
glide: {} // Glide
|
||||||
|
},
|
||||||
|
onCreate() {
|
||||||
|
this.data.glide = Glide.with();
|
||||||
|
app.setImageCacheCount(100);
|
||||||
|
app.setImageRawDataCacheSize(104857600)
|
||||||
|
app.setImageFileCacheSize(209715200)
|
||||||
|
},
|
||||||
|
onDestroy() {
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
export class Base64 {
|
||||||
|
lookup: Uint8Array = new Uint8Array(256)
|
||||||
|
chars: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
|
private static sInstance: Base64;
|
||||||
|
|
||||||
|
public static getInstance(): Base64{
|
||||||
|
if (!this.sInstance) {
|
||||||
|
this.sInstance = new Base64();
|
||||||
|
}
|
||||||
|
return this.sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
console.log("Base64 - constructor init!")
|
||||||
|
for (var index = 0; index < this.chars.length; index++) {
|
||||||
|
this.lookup[this.chars.charCodeAt(index)] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encode(arraybuffer: ArrayBuffer): string {
|
||||||
|
let bytes = new Uint8Array(arraybuffer),
|
||||||
|
i,
|
||||||
|
len = bytes.length,
|
||||||
|
base64 = '';
|
||||||
|
for (i = 0; i < len; i += 3) {
|
||||||
|
base64 += this.chars[bytes[i] >> 2];
|
||||||
|
base64 += this.chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
||||||
|
base64 += this.chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
||||||
|
base64 += this.chars[bytes[i + 2] & 63];
|
||||||
|
}
|
||||||
|
if (len % 3 === 2) {
|
||||||
|
base64 = base64.substring(0, base64.length - 1) + '=';
|
||||||
|
} else if (len % 3 === 1) {
|
||||||
|
base64 = base64.substring(0, base64.length - 2) + '==';
|
||||||
|
}
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
decode(base64: string): ArrayBuffer{
|
||||||
|
let bufferLength = base64.length * 0.75,
|
||||||
|
len = base64.length,
|
||||||
|
i,
|
||||||
|
p = 0,
|
||||||
|
encoded1,
|
||||||
|
encoded2,
|
||||||
|
encoded3,
|
||||||
|
encoded4;
|
||||||
|
|
||||||
|
if (base64[base64.length - 1] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
if (base64[base64.length - 2] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const arraybuffer = new ArrayBuffer(bufferLength),
|
||||||
|
bytes = new Uint8Array(arraybuffer);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 4) {
|
||||||
|
encoded1 = this.lookup[base64.charCodeAt(i)];
|
||||||
|
encoded2 = this.lookup[base64.charCodeAt(i + 1)];
|
||||||
|
encoded3 = this.lookup[base64.charCodeAt(i + 2)];
|
||||||
|
encoded4 = this.lookup[base64.charCodeAt(i + 3)];
|
||||||
|
|
||||||
|
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
||||||
|
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
||||||
|
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arraybuffer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http:// www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
export class CustomMap <K, V> {
|
||||||
|
map: Map<K, V> = new Map<K, V>()
|
||||||
|
|
||||||
|
// 获取键对应的值
|
||||||
|
get(key: K): V | undefined{
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
return this.map.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否含有key的缓存
|
||||||
|
*/
|
||||||
|
hasKey(key: K) {
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
return this.map.has(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加键值对
|
||||||
|
put(key: K, value: V): V | undefined{
|
||||||
|
if (key == null || value == null) {
|
||||||
|
throw new Error('key or value is invalid,checking the parameter');
|
||||||
|
}
|
||||||
|
var pre = this.map.get(key)
|
||||||
|
if (this.hasKey(key)) {
|
||||||
|
this.map.delete(key)
|
||||||
|
}
|
||||||
|
this.map.set(key, value);
|
||||||
|
return pre
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除键值,(去除键数据中的键名及对应的值)
|
||||||
|
remove(key: K): boolean {
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
return this.map.delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取最先存储的数据的key
|
||||||
|
*/
|
||||||
|
getFirstKey(): K{ // keys()可以遍历后需要优化put()方法,暂时仅获取index=0的key
|
||||||
|
return this.map.keys().next().value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断键值元素是否为空
|
||||||
|
isEmpty(): boolean{
|
||||||
|
return this.map.size == 0;
|
||||||
|
}
|
||||||
|
// 获取键值元素大小
|
||||||
|
size(): number{
|
||||||
|
return this.map.size;
|
||||||
|
}
|
||||||
|
// 遍历Map,执行处理函数. 回调函数 function(key,value,index){..}
|
||||||
|
each(fn) {
|
||||||
|
this.map.forEach(fn)
|
||||||
|
}
|
||||||
|
// 清除键值对
|
||||||
|
clear() {
|
||||||
|
this.map.clear()
|
||||||
|
}
|
||||||
|
// 遍历key
|
||||||
|
keys(): IterableIterator<K>{
|
||||||
|
return this.map.keys()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
export class DiskCacheEntry {
|
||||||
|
|
||||||
|
// 缓存的key
|
||||||
|
key: string= ''
|
||||||
|
|
||||||
|
// 缓存文件大小
|
||||||
|
length: number= 0
|
||||||
|
|
||||||
|
constructor(key: string, length?: number) {
|
||||||
|
this.key = key
|
||||||
|
this.length = length
|
||||||
|
}
|
||||||
|
|
||||||
|
setKey(key: string) {
|
||||||
|
this.key = key
|
||||||
|
}
|
||||||
|
|
||||||
|
getkey(): string{
|
||||||
|
return this.key
|
||||||
|
}
|
||||||
|
|
||||||
|
setLength(length: number) {
|
||||||
|
this.length = length
|
||||||
|
}
|
||||||
|
|
||||||
|
getLength(): number{
|
||||||
|
return this.length
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(): string{
|
||||||
|
return this.key + ' - ' + this.length
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,317 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {CustomMap} from './CustomMap'
|
||||||
|
import {FileUtils} from './FileUtils'
|
||||||
|
import {FileReader} from './FileReader'
|
||||||
|
import {DiskCacheEntry} from './DiskCacheEntry'
|
||||||
|
import fileio from '@ohos.fileio';
|
||||||
|
import featureability from '@ohos.ability.featureAbility'
|
||||||
|
import {Md5} from './Md5.ets'
|
||||||
|
|
||||||
|
export class DiskLruCache {
|
||||||
|
|
||||||
|
// 缓存数据集合
|
||||||
|
cacheMap: CustomMap<string, DiskCacheEntry> = new CustomMap<string, DiskCacheEntry>()
|
||||||
|
fileUtils: FileUtils = FileUtils.getInstance()
|
||||||
|
diskCacheFolder: string = 'GlideDiskCache'
|
||||||
|
|
||||||
|
// 缓存文件路劲地址
|
||||||
|
dirPath: string= ''
|
||||||
|
|
||||||
|
// 缓存数据最大值
|
||||||
|
maxSize: number = 30 * 1024 * 1024
|
||||||
|
|
||||||
|
// 当前缓存数据值
|
||||||
|
size: number = 0
|
||||||
|
|
||||||
|
// 缓存journal文件名称
|
||||||
|
|
||||||
|
journal: string = 'journal'
|
||||||
|
|
||||||
|
// 缓存journal备份文件名称
|
||||||
|
journalTemp: string = 'journal_temp'
|
||||||
|
|
||||||
|
// 缓存journal文件路径
|
||||||
|
journalPath: string = ''
|
||||||
|
|
||||||
|
// 缓存journal备份文件路径
|
||||||
|
journalPathTemp: string = ''
|
||||||
|
|
||||||
|
constructor(maxSize: number, direction?: string) {
|
||||||
|
if (maxSize > 0) {
|
||||||
|
this.maxSize = maxSize
|
||||||
|
}
|
||||||
|
if (!this.isNull(direction)) {
|
||||||
|
if (direction.endsWith('/')) {
|
||||||
|
this.dirPath = direction
|
||||||
|
} else {
|
||||||
|
this.dirPath = direction + '/'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
featureability.getContext()
|
||||||
|
.getFilesDir()
|
||||||
|
.then((data) => {
|
||||||
|
console.log('DiskLruCache - FileDir= ' + data)
|
||||||
|
let dirPathFolder = data + '/' + this.diskCacheFolder
|
||||||
|
this.dirPath = dirPathFolder;
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.createFolder(dirPathFolder)
|
||||||
|
this.init()
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log('DiskLruCache FileDir Error Cause:' + error.message);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化缓存文件
|
||||||
|
*/
|
||||||
|
private init() {
|
||||||
|
if (this.dirPath.endsWith('/')) {
|
||||||
|
this.dirPath = this.dirPath
|
||||||
|
} else {
|
||||||
|
this.dirPath = this.dirPath + '/'
|
||||||
|
}
|
||||||
|
this.journalPath = this.dirPath + this.journal
|
||||||
|
this.journalPathTemp = this.dirPath + this.journalTemp
|
||||||
|
try {
|
||||||
|
var stat = fileio.statSync(this.journalPath)
|
||||||
|
if (stat.isFile() && stat.size > 0) {
|
||||||
|
this.fileUtils.createFile(this.journalPathTemp)
|
||||||
|
this.fileUtils.copyFile(this.journalPath, this.journalPathTemp)
|
||||||
|
this.readJournal(this.journalPathTemp)
|
||||||
|
this.resetJournalFile()
|
||||||
|
} else {
|
||||||
|
this.fileUtils.createFile(this.journalPath)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('DiskLruCache - init e ' + e)
|
||||||
|
this.fileUtils.createFile(this.journalPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置journal文件数据
|
||||||
|
*/
|
||||||
|
resetJournalFile(){
|
||||||
|
this.fileUtils.clearFile(this.journalPath)
|
||||||
|
for(let key of this.cacheMap.keys()){
|
||||||
|
this.fileUtils.writeData(this.journalPath, 'save ' + key + '\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取journal文件的缓存数据
|
||||||
|
*/
|
||||||
|
readJournal(path: string) {
|
||||||
|
var fileReader = new FileReader(path)
|
||||||
|
var line: string = ''
|
||||||
|
while (!fileReader.isEnd()) {
|
||||||
|
line = fileReader.readLine()
|
||||||
|
line = line.replace('\n', '').replace('\r', '')
|
||||||
|
this.dealwithJournal(line)
|
||||||
|
}
|
||||||
|
this.fileUtils.deleteFile(this.journalPathTemp)
|
||||||
|
this.trimToSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理journal文件数据
|
||||||
|
*/
|
||||||
|
dealwithJournal(line: string) {
|
||||||
|
var picPath = ''
|
||||||
|
try {
|
||||||
|
var datas = line.split(' ')
|
||||||
|
if (datas.length > 1) {
|
||||||
|
if (datas[0] != 'remove') {
|
||||||
|
picPath = this.dirPath + datas[1]
|
||||||
|
var picstat = fileio.statSync(picPath)
|
||||||
|
if (picstat.isFile() && picstat.size > 0) {
|
||||||
|
this.size = this.size + picstat.size
|
||||||
|
this.fileUtils.writeData(this.journalPath, line + '\n')
|
||||||
|
this.putCacheMap(datas[1], picstat.size)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.cacheMap.hasKey(datas[1])) {
|
||||||
|
var cacheEntry: DiskCacheEntry = this.cacheMap.get(datas[1])
|
||||||
|
this.size = this.size - cacheEntry.getLength()
|
||||||
|
this.cacheMap.remove(datas[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('DiskLruCache - dealwithJournal e = ' + e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置disk缓存最大数据值
|
||||||
|
*/
|
||||||
|
setMaxSize(max: number) {
|
||||||
|
this.maxSize = max
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存数据map集合
|
||||||
|
*/
|
||||||
|
private putCacheMap(key: string, length?: number) {
|
||||||
|
if (this.cacheMap.hasKey(key)) {
|
||||||
|
this.cacheMap.remove(key)
|
||||||
|
}
|
||||||
|
if (length > 0) {
|
||||||
|
this.cacheMap.put(key, new DiskCacheEntry(key, length))
|
||||||
|
} else {
|
||||||
|
this.cacheMap.put(key, new DiskCacheEntry(key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储disk缓存数据
|
||||||
|
*/
|
||||||
|
putCacheData(key: string, content?: ArrayBuffer, path?: string) {
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
var fileSize = 0
|
||||||
|
var isvalid: boolean = false
|
||||||
|
key = Md5.hashStr(key)
|
||||||
|
if (content != null && content.byteLength > 0) {
|
||||||
|
isvalid = true
|
||||||
|
var tempPath = this.dirPath + key
|
||||||
|
fileSize = content.byteLength
|
||||||
|
this.fileUtils.writePic(tempPath, content)
|
||||||
|
}
|
||||||
|
if (!this.isNull(path) && this.fileUtils.exist(path)) {
|
||||||
|
isvalid = true
|
||||||
|
fileSize = this.fileUtils.getFileSize(path)
|
||||||
|
this.fileUtils.copyFile(path, this.dirPath + key)
|
||||||
|
}
|
||||||
|
if (isvalid) {
|
||||||
|
this.size = this.size + fileSize
|
||||||
|
this.putCacheMap(key, fileSize)
|
||||||
|
this.fileUtils.writeData(this.journalPath, 'save ' + key + '\n')
|
||||||
|
this.trimToSize()
|
||||||
|
} else {
|
||||||
|
throw ('putCacheData() key or content or path is invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据LRU算法删除多余缓存数据
|
||||||
|
*/
|
||||||
|
private trimToSize() {
|
||||||
|
while (this.size > this.maxSize) {
|
||||||
|
var tempkey: string = this.cacheMap.getFirstKey()
|
||||||
|
var fileSize = this.fileUtils.getFileSize(this.dirPath + tempkey)
|
||||||
|
if (fileSize > 0) {
|
||||||
|
this.size = this.size - fileSize
|
||||||
|
}
|
||||||
|
this.fileUtils.deleteFile(this.dirPath + tempkey)
|
||||||
|
this.cacheMap.remove(tempkey)
|
||||||
|
this.fileUtils.writeData(this.journalPath, 'remove ' + tempkey + '\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取key缓存数据
|
||||||
|
*/
|
||||||
|
getCacheDataByKey(key: string): ArrayBuffer{
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
key = Md5.hashStr(key)
|
||||||
|
var path = this.dirPath + key;
|
||||||
|
if (this.fileUtils.exist(path)) {
|
||||||
|
var ab: ArrayBuffer = this.fileUtils.readFilePic(path)
|
||||||
|
this.putCacheMap(key, ab.byteLength)
|
||||||
|
this.fileUtils.writeData(path, 'read ' + key + '\n')
|
||||||
|
return ab
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取key缓存数据绝对路径
|
||||||
|
*/
|
||||||
|
getCacheFileByKey(key: string): string{
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
key = Md5.hashStr(key)
|
||||||
|
if (this.dirPath.endsWith('/')) {
|
||||||
|
this.dirPath = this.dirPath
|
||||||
|
} else {
|
||||||
|
this.dirPath = this.dirPath + '/'
|
||||||
|
}
|
||||||
|
var path = this.dirPath + key;
|
||||||
|
if (this.fileUtils.exist(path)) {
|
||||||
|
this.fileUtils.writeData(path, 'read ' + key + '\n')
|
||||||
|
return path
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除key缓存数据
|
||||||
|
*/
|
||||||
|
deleteCacheDataBykey(key: string): DiskCacheEntry{
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
key = Md5.hashStr(key)
|
||||||
|
var path = this.dirPath + key;
|
||||||
|
if (this.fileUtils.exist(path)) {
|
||||||
|
var ab = this.fileUtils.readFilePic(path)
|
||||||
|
this.size = this.size - ab.byteLength
|
||||||
|
this.cacheMap.remove(key)
|
||||||
|
this.fileUtils.writeData(this.journalPath, 'remove ' + key + '\n')
|
||||||
|
this.fileUtils.deleteFile(path)
|
||||||
|
}
|
||||||
|
return this.cacheMap.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有disk缓存数据
|
||||||
|
*/
|
||||||
|
cleanCacheData() {
|
||||||
|
var length = this.cacheMap.size()
|
||||||
|
for (var index = 0; index < length; index++) {
|
||||||
|
this.fileUtils.deleteFile(this.dirPath + this.cacheMap[index])
|
||||||
|
}
|
||||||
|
this.fileUtils.deleteFile(this.journalPath)
|
||||||
|
this.cacheMap.clear()
|
||||||
|
this.size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空字符串判断
|
||||||
|
*/
|
||||||
|
private isNull(str: string): boolean{
|
||||||
|
if (!str || Object.keys(str).length == 0) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreachDiskLruCache(fn){
|
||||||
|
this.cacheMap.each(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import fileio from '@ohos.fileio';
|
||||||
|
|
||||||
|
export class FileReader {
|
||||||
|
|
||||||
|
// 文件大小
|
||||||
|
fileLength: number = 0
|
||||||
|
|
||||||
|
// 读取的长度
|
||||||
|
length: number = 0
|
||||||
|
|
||||||
|
// 读写stream
|
||||||
|
stream: any = null
|
||||||
|
// 缓存buf
|
||||||
|
buf: ArrayBuffer = new ArrayBuffer(1)
|
||||||
|
|
||||||
|
constructor(path: string) {
|
||||||
|
if (!path || Object.keys(path).length == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.stream = fileio.createStreamSync(path, 'r+');
|
||||||
|
var stat = fileio.statSync(path)
|
||||||
|
this.fileLength = stat.size
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 循环读取文件数据
|
||||||
|
*/
|
||||||
|
readLine(): string{
|
||||||
|
var line = ''
|
||||||
|
while (this.length <= this.fileLength) {
|
||||||
|
this.stream.readSync(this.buf, { position: this.length })
|
||||||
|
this.length++
|
||||||
|
var temp = String.fromCharCode.apply(null, new Uint8Array(this.buf));
|
||||||
|
line = line + temp
|
||||||
|
if (temp == '\n' || temp == '\r') {
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断文件是否结束
|
||||||
|
*/
|
||||||
|
isEnd() {
|
||||||
|
return this.fileLength <= 0 || this.length == this.fileLength
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭stream
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
this.stream.closeSync()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,316 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import resmgr from '@ohos.resourceManager'
|
||||||
|
import fileio from '@ohos.fileio';
|
||||||
|
|
||||||
|
export class FileUtils {
|
||||||
|
base64Str: string= ''
|
||||||
|
|
||||||
|
private static sInstance: FileUtils;
|
||||||
|
|
||||||
|
public static getInstance(): FileUtils{
|
||||||
|
if (!this.sInstance) {
|
||||||
|
this.sInstance = new FileUtils();
|
||||||
|
}
|
||||||
|
return this.sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
console.error("FileUtils - FileUtils constructor")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新建文件
|
||||||
|
* @param path 文件绝对路径及文件名
|
||||||
|
* @return number 文件句柄id
|
||||||
|
*/
|
||||||
|
createFile(path: string): number{
|
||||||
|
return fileio.openSync(path, 0o100, 0o666)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文件
|
||||||
|
* @param path 文件绝对路径及文件名
|
||||||
|
*/
|
||||||
|
deleteFile(path: string):void {
|
||||||
|
fileio.unlinkSync(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步删除文件目录 必须保证文件夹里面没有文件
|
||||||
|
* @param path 待删除目录的绝对路径
|
||||||
|
*/
|
||||||
|
deleteFolderSync(path: string):void {
|
||||||
|
if (this.existFolder(path)) {
|
||||||
|
fileio.rmdirSync(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步删除文件目录 必须保证文件夹里面没有文件
|
||||||
|
* @param path 待删除目录的绝对路径
|
||||||
|
*/
|
||||||
|
deleteFolderAsync(path: string, deleteComplete, deleteError) {
|
||||||
|
if (this.existFolder(path)) {
|
||||||
|
fileio.rmdir(path)
|
||||||
|
.then(deleteComplete).catch(deleteError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝文件
|
||||||
|
* @param path 文件绝对路径及文件名
|
||||||
|
*/
|
||||||
|
copyFile(oriPath: string, newPath: string) {
|
||||||
|
fileio.copyFileSync(oriPath, newPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空已有文件数据
|
||||||
|
*/
|
||||||
|
clearFile(path: string):number {
|
||||||
|
return fileio.openSync(path, 0o1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向path写入content数据,覆盖旧数据
|
||||||
|
*/
|
||||||
|
writeFile(path: string, content: ArrayBuffer | string) {
|
||||||
|
try {
|
||||||
|
let fd = fileio.openSync(path, 0o102, 0o666)
|
||||||
|
fileio.ftruncateSync(fd)
|
||||||
|
fileio.writeSync(fd, content)
|
||||||
|
fileio.fsyncSync(fd)
|
||||||
|
fileio.closeSync(fd)
|
||||||
|
} catch (e) {
|
||||||
|
console.log("FileUtils - Failed to writeFile for " + e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向path写入数据
|
||||||
|
*/
|
||||||
|
writeData(path: string, content: ArrayBuffer | string) {
|
||||||
|
try {
|
||||||
|
console.info("FileUtils - writeData size 1= " + path)
|
||||||
|
let fd = fileio.openSync(path, 0o102, 0o666)
|
||||||
|
console.info("FileUtils - writeData size 2= ")
|
||||||
|
let stat = fileio.statSync(path)
|
||||||
|
console.info("FileUtils - writeData size = " + stat.size)
|
||||||
|
fileio.writeSync(fd, content, { position: stat.size })
|
||||||
|
let length = 0
|
||||||
|
if (content instanceof ArrayBuffer) {
|
||||||
|
length = content.byteLength
|
||||||
|
} else {
|
||||||
|
length = content.length
|
||||||
|
}
|
||||||
|
fileio.closeSync(fd)
|
||||||
|
} catch (e) {
|
||||||
|
console.log("FileUtils - Failed to writeData for " + e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断path文件是否存在
|
||||||
|
*/
|
||||||
|
exist(path: string): boolean{
|
||||||
|
try {
|
||||||
|
let stat = fileio.statSync(path)
|
||||||
|
return stat.isFile()
|
||||||
|
} catch (e) {
|
||||||
|
console.debug("FileUtils - fileutils exsit e" + e)
|
||||||
|
console.log("path=>" + path)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向path写入数据
|
||||||
|
*/
|
||||||
|
writePic(path: string, picData: ArrayBuffer) {
|
||||||
|
console.info("FileUtils - writepic 1")
|
||||||
|
this.createFile(path)
|
||||||
|
this.writeFile(path, picData)
|
||||||
|
console.info("FileUtils - writepic 3")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取path的文件大小
|
||||||
|
*/
|
||||||
|
getFileSize(path: string): number{
|
||||||
|
try {
|
||||||
|
let stat = fileio.statSync(path)
|
||||||
|
return stat.size
|
||||||
|
} catch (e) {
|
||||||
|
console.error("FileUtils - FileUtils getFileSize e " + e)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取路径path的文件
|
||||||
|
*/
|
||||||
|
readFilePic(path: string): ArrayBuffer {
|
||||||
|
try {
|
||||||
|
let stat = fileio.statSync(path)
|
||||||
|
console.info("FileUtils - readFilePic 1")
|
||||||
|
let fd = fileio.openSync(path, 0o2);
|
||||||
|
let length = fileio.statSync(path).size
|
||||||
|
console.info("FileUtils - readFilePic 2 length = " + length)
|
||||||
|
let buf = new ArrayBuffer(length);
|
||||||
|
console.info("FileUtils - readFilePic 3")
|
||||||
|
fileio.readSync(fd, buf)
|
||||||
|
return buf
|
||||||
|
} catch (e) {
|
||||||
|
console.log("FileUtils - readFilePic " + e)
|
||||||
|
return new ArrayBuffer(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取media的资源文件
|
||||||
|
*/
|
||||||
|
readMediaPic() {
|
||||||
|
resmgr.getResourceManager()
|
||||||
|
.then(result => {
|
||||||
|
result.getMediaBase64($r('app.media.icon')
|
||||||
|
.id)
|
||||||
|
.then(data => {
|
||||||
|
console.error("FileUtils - readPic data = " + data)
|
||||||
|
data = data.replace("data:image/png;base64,", "")
|
||||||
|
console.error("FileUtils - readPic this.data = " + data)
|
||||||
|
this.base64Str = data
|
||||||
|
console.error("FileUtils - readPic this.base64Str = " + this.base64Str)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log("FileUtils - readPic err" + JSON.stringify(err));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stream式读取
|
||||||
|
*/
|
||||||
|
readStream(path: string): string {
|
||||||
|
try {
|
||||||
|
let stat = fileio.statSync(path)
|
||||||
|
let length = stat.size
|
||||||
|
let buf = new ArrayBuffer(length);
|
||||||
|
let ss = fileio.createStreamSync(path, "r+");
|
||||||
|
ss.readSync(buf)
|
||||||
|
ss.closeSync();
|
||||||
|
return String.fromCharCode.apply(null, new Uint8Array(buf))
|
||||||
|
} catch (e) {
|
||||||
|
console.log("FileUtils - readFilePic " + e)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stream式写入
|
||||||
|
*/
|
||||||
|
writeStream(path: string, tempArray: ArrayBuffer) {
|
||||||
|
try {
|
||||||
|
console.error("FileUtils - writeStream =1 ")
|
||||||
|
this.createFile(path)
|
||||||
|
console.error("FileUtils - writeStream 2 ")
|
||||||
|
let ss = fileio.createStreamSync(path, "r+");
|
||||||
|
console.error("FileUtils - writeStream 3 " + tempArray.byteLength)
|
||||||
|
let num = ss.writeSync(tempArray, {
|
||||||
|
encoding: 'utf-8'
|
||||||
|
});
|
||||||
|
console.error("FileUtils - write num = " + num)
|
||||||
|
ss.flushSync();
|
||||||
|
ss.closeSync();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("FileUtils - Failed to writeStream for " + e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建文件夹
|
||||||
|
* @param 文件夹绝对路径
|
||||||
|
*/
|
||||||
|
createFolder(path: string) {
|
||||||
|
//创建文件夹
|
||||||
|
if (!this.existFolder(path)) {
|
||||||
|
fileio.mkdirSync(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断文件夹是否存在
|
||||||
|
* @param 文件夹绝对路径
|
||||||
|
*/
|
||||||
|
existFolder(path: string): boolean{
|
||||||
|
try {
|
||||||
|
let stat = fileio.statSync(path)
|
||||||
|
return stat.isDirectory()
|
||||||
|
} catch (e) {
|
||||||
|
console.debug("fileutils folder exsit error=" + e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果文件夹不存在则创建一个文件夹 然后在其中创建文件 并且将数据写入进文件
|
||||||
|
* @param folder 文件夹绝对路径
|
||||||
|
* @param file 文件绝对路径
|
||||||
|
* @param content 文件内容数据
|
||||||
|
*/
|
||||||
|
createFileProcess(folder: string, file: string, content: ArrayBuffer | string) {
|
||||||
|
//创建文件夹
|
||||||
|
this.createFolder(folder);
|
||||||
|
//创建文件
|
||||||
|
this.createFile(file);
|
||||||
|
//写入数据
|
||||||
|
this.writeFile(file, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string 转 Uint8Array
|
||||||
|
* @param str 输入String
|
||||||
|
*/
|
||||||
|
stringToUint8Array(str): Uint8Array{
|
||||||
|
var arr = [];
|
||||||
|
for (var i = 0, j = str.length; i < j; ++i) {
|
||||||
|
arr.push(str.charCodeAt(i));
|
||||||
|
}
|
||||||
|
var tmpUint8Array = new Uint8Array(arr);
|
||||||
|
return tmpUint8Array
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* int 转 byte[]
|
||||||
|
* @param n 输入int
|
||||||
|
*/
|
||||||
|
intTobytes2(n) {
|
||||||
|
var bytes = [];
|
||||||
|
for (var i = 0; i < 2; i++) {
|
||||||
|
bytes[i] = n >> (8 - i * 8);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8ArrayToBuffer(array: Uint8Array): ArrayBuffer {
|
||||||
|
return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AsyncCallback<T> {
|
||||||
|
(err: string, data: T): void;
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http:// www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {CustomMap} from './CustomMap'
|
||||||
|
|
||||||
|
export class LruCache <K, V> {
|
||||||
|
maxsize: number = 0
|
||||||
|
size: number = 0;
|
||||||
|
map: CustomMap<K, V> = new CustomMap<K, V>();
|
||||||
|
|
||||||
|
constructor(maxsize: number) {
|
||||||
|
this.trimToSize(-1)
|
||||||
|
this.maxsize = maxsize
|
||||||
|
this.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加缓存键值对
|
||||||
|
put(key: K, value: V) {
|
||||||
|
if (key == null || value == null) {
|
||||||
|
throw new Error('key or value is invalid ');
|
||||||
|
}
|
||||||
|
var pre = this.map.get(key)
|
||||||
|
if (pre == null) {
|
||||||
|
this.size++
|
||||||
|
}
|
||||||
|
this.entryRemoved(key, pre, value)
|
||||||
|
this.trimToSize(this.maxsize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除键为key的缓存
|
||||||
|
remove(key: K): V | undefined{
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
var preValue = this.map.get(key)
|
||||||
|
if (this.map.remove(key)) {
|
||||||
|
this.size--
|
||||||
|
}
|
||||||
|
return preValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取键为key的value
|
||||||
|
get(key: K): V {
|
||||||
|
if (key == null) {
|
||||||
|
throw new Error('key is null,checking the parameter');
|
||||||
|
}
|
||||||
|
var preValue = this.map.get(key)
|
||||||
|
if (preValue != null) {
|
||||||
|
this.entryRemoved(key, preValue, preValue)
|
||||||
|
}
|
||||||
|
return preValue
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 替换或删除对应key键的数据
|
||||||
|
* evicted:是否删除
|
||||||
|
* key:对应的键值key
|
||||||
|
* preValue 对应key键的旧value值
|
||||||
|
* value 对应key键的新value值
|
||||||
|
*/
|
||||||
|
entryRemoved(key: K, preValue: V, value: V) {
|
||||||
|
if (preValue != null) {
|
||||||
|
this.map.remove(key)
|
||||||
|
}
|
||||||
|
if (value != null) {
|
||||||
|
this.map.put(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除较少使用的缓存数据
|
||||||
|
trimToSize(tempsize: number) {
|
||||||
|
while (true) {
|
||||||
|
if (tempsize < 0) {
|
||||||
|
this.map.clear()
|
||||||
|
this.size = 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (this.size <= tempsize || this.map.isEmpty()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
var delkey = this.map.getFirstKey()
|
||||||
|
this.map.remove(delkey)
|
||||||
|
this.size--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存数据数量
|
||||||
|
sizeLength(): number{
|
||||||
|
return this.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存数据最大值
|
||||||
|
maxSize(): number{
|
||||||
|
return this.maxsize
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置缓存数据量最大值
|
||||||
|
resize(maxsize: number) {
|
||||||
|
if (maxsize < 0) {
|
||||||
|
throw new Error('maxsize <0 & maxsize invalid');
|
||||||
|
}
|
||||||
|
this.maxsize = maxsize
|
||||||
|
this.trimToSize(maxsize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除缓存
|
||||||
|
evicAll() {
|
||||||
|
this.trimToSize(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
print():string {
|
||||||
|
let printResult = '';
|
||||||
|
if (this.map.isEmpty()) {
|
||||||
|
return printResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.map.each(function (value, key, index) {
|
||||||
|
printResult +='LruCache:key=' + key + 'value= ' + value;
|
||||||
|
})
|
||||||
|
return printResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreachLruCache(fn){
|
||||||
|
this.map.each(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,392 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
export class Md5 {
|
||||||
|
|
||||||
|
// One time hashing functions
|
||||||
|
public static hashStr(str: string, raw?: false): string
|
||||||
|
|
||||||
|
public static hashStr(str: string, raw: true): Int32Array
|
||||||
|
|
||||||
|
public static hashStr(str: string, raw: boolean = false) {
|
||||||
|
return this.onePassHasher
|
||||||
|
.start()
|
||||||
|
.appendStr(str)
|
||||||
|
.end(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static hashAsciiStr(str: string, raw?: false): string
|
||||||
|
|
||||||
|
public static hashAsciiStr(str: string, raw: true): Int32Array
|
||||||
|
|
||||||
|
public static hashAsciiStr(str: string, raw: boolean = false) {
|
||||||
|
return this.onePassHasher
|
||||||
|
.start()
|
||||||
|
.appendAsciiStr(str)
|
||||||
|
.end(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Static Variables
|
||||||
|
private static stateIdentity = new Int32Array([1732584193, -271733879, -1732584194, 271733878]);
|
||||||
|
private static buffer32Identity = new Int32Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
private static hexChars = '0123456789abcdef';
|
||||||
|
private static hexOut: string[] = [];
|
||||||
|
|
||||||
|
// Permanent instance is to use for one-call hashing
|
||||||
|
private static onePassHasher = new Md5();
|
||||||
|
|
||||||
|
private static _hex(x: any): string {
|
||||||
|
const hc = Md5.hexChars;
|
||||||
|
const ho = Md5.hexOut;
|
||||||
|
let n;
|
||||||
|
let offset;
|
||||||
|
let j;
|
||||||
|
let i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i += 1) {
|
||||||
|
offset = i * 8;
|
||||||
|
n = x[i];
|
||||||
|
for (j = 0; j < 8; j += 2) {
|
||||||
|
ho[offset + 1 + j] = hc.charAt(n & 0x0F);
|
||||||
|
n >>>= 4;
|
||||||
|
ho[offset + 0 + j] = hc.charAt(n & 0x0F);
|
||||||
|
n >>>= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ho.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static _md5cycle(x: Int32Array | Uint32Array, k: Int32Array | Uint32Array) {
|
||||||
|
let a = x[0];
|
||||||
|
let b = x[1];
|
||||||
|
let c = x[2];
|
||||||
|
let d = x[3];
|
||||||
|
// ff()
|
||||||
|
a += (b & c | ~b & d) + k[0] - 680876936 | 0;
|
||||||
|
a = (a << 7 | a >>> 25) + b | 0;
|
||||||
|
d += (a & b | ~a & c) + k[1] - 389564586 | 0;
|
||||||
|
d = (d << 12 | d >>> 20) + a | 0;
|
||||||
|
c += (d & a | ~d & b) + k[2] + 606105819 | 0;
|
||||||
|
c = (c << 17 | c >>> 15) + d | 0;
|
||||||
|
b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
|
||||||
|
b = (b << 22 | b >>> 10) + c | 0;
|
||||||
|
a += (b & c | ~b & d) + k[4] - 176418897 | 0;
|
||||||
|
a = (a << 7 | a >>> 25) + b | 0;
|
||||||
|
d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
|
||||||
|
d = (d << 12 | d >>> 20) + a | 0;
|
||||||
|
c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
|
||||||
|
c = (c << 17 | c >>> 15) + d | 0;
|
||||||
|
b += (c & d | ~c & a) + k[7] - 45705983 | 0;
|
||||||
|
b = (b << 22 | b >>> 10) + c | 0;
|
||||||
|
a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
|
||||||
|
a = (a << 7 | a >>> 25) + b | 0;
|
||||||
|
d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
|
||||||
|
d = (d << 12 | d >>> 20) + a | 0;
|
||||||
|
c += (d & a | ~d & b) + k[10] - 42063 | 0;
|
||||||
|
c = (c << 17 | c >>> 15) + d | 0;
|
||||||
|
b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
|
||||||
|
b = (b << 22 | b >>> 10) + c | 0;
|
||||||
|
a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
|
||||||
|
a = (a << 7 | a >>> 25) + b | 0;
|
||||||
|
d += (a & b | ~a & c) + k[13] - 40341101 | 0;
|
||||||
|
d = (d << 12 | d >>> 20) + a | 0;
|
||||||
|
c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
|
||||||
|
c = (c << 17 | c >>> 15) + d | 0;
|
||||||
|
b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
|
||||||
|
b = (b << 22 | b >>> 10) + c | 0;
|
||||||
|
// gg()
|
||||||
|
a += (b & d | c & ~d) + k[1] - 165796510 | 0;
|
||||||
|
a = (a << 5 | a >>> 27) + b | 0;
|
||||||
|
d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
|
||||||
|
d = (d << 9 | d >>> 23) + a | 0;
|
||||||
|
c += (d & b | a & ~b) + k[11] + 643717713 | 0;
|
||||||
|
c = (c << 14 | c >>> 18) + d | 0;
|
||||||
|
b += (c & a | d & ~a) + k[0] - 373897302 | 0;
|
||||||
|
b = (b << 20 | b >>> 12) + c | 0;
|
||||||
|
a += (b & d | c & ~d) + k[5] - 701558691 | 0;
|
||||||
|
a = (a << 5 | a >>> 27) + b | 0;
|
||||||
|
d += (a & c | b & ~c) + k[10] + 38016083 | 0;
|
||||||
|
d = (d << 9 | d >>> 23) + a | 0;
|
||||||
|
c += (d & b | a & ~b) + k[15] - 660478335 | 0;
|
||||||
|
c = (c << 14 | c >>> 18) + d | 0;
|
||||||
|
b += (c & a | d & ~a) + k[4] - 405537848 | 0;
|
||||||
|
b = (b << 20 | b >>> 12) + c | 0;
|
||||||
|
a += (b & d | c & ~d) + k[9] + 568446438 | 0;
|
||||||
|
a = (a << 5 | a >>> 27) + b | 0;
|
||||||
|
d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
|
||||||
|
d = (d << 9 | d >>> 23) + a | 0;
|
||||||
|
c += (d & b | a & ~b) + k[3] - 187363961 | 0;
|
||||||
|
c = (c << 14 | c >>> 18) + d | 0;
|
||||||
|
b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
|
||||||
|
b = (b << 20 | b >>> 12) + c | 0;
|
||||||
|
a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
|
||||||
|
a = (a << 5 | a >>> 27) + b | 0;
|
||||||
|
d += (a & c | b & ~c) + k[2] - 51403784 | 0;
|
||||||
|
d = (d << 9 | d >>> 23) + a | 0;
|
||||||
|
c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
|
||||||
|
c = (c << 14 | c >>> 18) + d | 0;
|
||||||
|
b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
|
||||||
|
b = (b << 20 | b >>> 12) + c | 0;
|
||||||
|
// hh()
|
||||||
|
a += (b ^ c ^ d) + k[5] - 378558 | 0;
|
||||||
|
a = (a << 4 | a >>> 28) + b | 0;
|
||||||
|
d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
|
||||||
|
d = (d << 11 | d >>> 21) + a | 0;
|
||||||
|
c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
|
||||||
|
c = (c << 16 | c >>> 16) + d | 0;
|
||||||
|
b += (c ^ d ^ a) + k[14] - 35309556 | 0;
|
||||||
|
b = (b << 23 | b >>> 9) + c | 0;
|
||||||
|
a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
|
||||||
|
a = (a << 4 | a >>> 28) + b | 0;
|
||||||
|
d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
|
||||||
|
d = (d << 11 | d >>> 21) + a | 0;
|
||||||
|
c += (d ^ a ^ b) + k[7] - 155497632 | 0;
|
||||||
|
c = (c << 16 | c >>> 16) + d | 0;
|
||||||
|
b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
|
||||||
|
b = (b << 23 | b >>> 9) + c | 0;
|
||||||
|
a += (b ^ c ^ d) + k[13] + 681279174 | 0;
|
||||||
|
a = (a << 4 | a >>> 28) + b | 0;
|
||||||
|
d += (a ^ b ^ c) + k[0] - 358537222 | 0;
|
||||||
|
d = (d << 11 | d >>> 21) + a | 0;
|
||||||
|
c += (d ^ a ^ b) + k[3] - 722521979 | 0;
|
||||||
|
c = (c << 16 | c >>> 16) + d | 0;
|
||||||
|
b += (c ^ d ^ a) + k[6] + 76029189 | 0;
|
||||||
|
b = (b << 23 | b >>> 9) + c | 0;
|
||||||
|
a += (b ^ c ^ d) + k[9] - 640364487 | 0;
|
||||||
|
a = (a << 4 | a >>> 28) + b | 0;
|
||||||
|
d += (a ^ b ^ c) + k[12] - 421815835 | 0;
|
||||||
|
d = (d << 11 | d >>> 21) + a | 0;
|
||||||
|
c += (d ^ a ^ b) + k[15] + 530742520 | 0;
|
||||||
|
c = (c << 16 | c >>> 16) + d | 0;
|
||||||
|
b += (c ^ d ^ a) + k[2] - 995338651 | 0;
|
||||||
|
b = (b << 23 | b >>> 9) + c | 0;
|
||||||
|
// ii()
|
||||||
|
a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
|
||||||
|
a = (a << 6 | a >>> 26) + b | 0;
|
||||||
|
d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
|
||||||
|
d = (d << 10 | d >>> 22) + a | 0;
|
||||||
|
c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
|
||||||
|
c = (c << 15 | c >>> 17) + d | 0;
|
||||||
|
b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
|
||||||
|
b = (b << 21 | b >>> 11) + c | 0;
|
||||||
|
a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
|
||||||
|
a = (a << 6 | a >>> 26) + b | 0;
|
||||||
|
d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
|
||||||
|
d = (d << 10 | d >>> 22) + a | 0;
|
||||||
|
c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
|
||||||
|
c = (c << 15 | c >>> 17) + d | 0;
|
||||||
|
b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
|
||||||
|
b = (b << 21 | b >>> 11) + c | 0;
|
||||||
|
a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
|
||||||
|
a = (a << 6 | a >>> 26) + b | 0;
|
||||||
|
d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
|
||||||
|
d = (d << 10 | d >>> 22) + a | 0;
|
||||||
|
c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
|
||||||
|
c = (c << 15 | c >>> 17) + d | 0;
|
||||||
|
b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
|
||||||
|
b = (b << 21 | b >>> 11) + c | 0;
|
||||||
|
a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
|
||||||
|
a = (a << 6 | a >>> 26) + b | 0;
|
||||||
|
d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
|
||||||
|
d = (d << 10 | d >>> 22) + a | 0;
|
||||||
|
c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
|
||||||
|
c = (c << 15 | c >>> 17) + d | 0;
|
||||||
|
b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
|
||||||
|
b = (b << 21 | b >>> 11) + c | 0;
|
||||||
|
|
||||||
|
x[0] = a + x[0] | 0;
|
||||||
|
x[1] = b + x[1] | 0;
|
||||||
|
x[2] = c + x[2] | 0;
|
||||||
|
x[3] = d + x[3] | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _dataLength: number;
|
||||||
|
private _bufferLength: number;
|
||||||
|
private _state: Int32Array = new Int32Array(4);
|
||||||
|
private _buffer: ArrayBuffer = new ArrayBuffer(68);
|
||||||
|
private _buffer8: Uint8Array;
|
||||||
|
private _buffer32: Uint32Array;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._buffer8 = new Uint8Array(this._buffer, 0, 68);
|
||||||
|
this._buffer32 = new Uint32Array(this._buffer, 0, 17);
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public start() {
|
||||||
|
this._dataLength = 0;
|
||||||
|
this._bufferLength = 0;
|
||||||
|
this._state.set(Md5.stateIdentity);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Char to code point to to array conversion:
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
|
||||||
|
// #Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown
|
||||||
|
public appendStr(str: string) {
|
||||||
|
const buf8 = this._buffer8;
|
||||||
|
const buf32 = this._buffer32;
|
||||||
|
let bufLen = this._bufferLength;
|
||||||
|
let code;
|
||||||
|
let i;
|
||||||
|
|
||||||
|
for (i = 0; i < str.length; i += 1) {
|
||||||
|
code = str.charCodeAt(i);
|
||||||
|
if (code < 128) {
|
||||||
|
buf8[bufLen++] = code;
|
||||||
|
} else if (code < 0x800) {
|
||||||
|
buf8[bufLen++] = (code >>> 6) + 0xC0;
|
||||||
|
buf8[bufLen++] = code & 0x3F | 0x80;
|
||||||
|
} else if (code < 0xD800 || code > 0xDBFF) {
|
||||||
|
buf8[bufLen++] = (code >>> 12) + 0xE0;
|
||||||
|
buf8[bufLen++] = (code >>> 6 & 0x3F) | 0x80;
|
||||||
|
buf8[bufLen++] = (code & 0x3F) | 0x80;
|
||||||
|
} else {
|
||||||
|
code = ((code - 0xD800) * 0x400) + (str.charCodeAt(++i) - 0xDC00) + 0x10000;
|
||||||
|
if (code > 0x10FFFF) {
|
||||||
|
throw new Error('Unicode standard supports code points up to U+10FFFF');
|
||||||
|
}
|
||||||
|
buf8[bufLen++] = (code >>> 18) + 0xF0;
|
||||||
|
buf8[bufLen++] = (code >>> 12 & 0x3F) | 0x80;
|
||||||
|
buf8[bufLen++] = (code >>> 6 & 0x3F) | 0x80;
|
||||||
|
buf8[bufLen++] = (code & 0x3F) | 0x80;
|
||||||
|
}
|
||||||
|
if (bufLen >= 64) {
|
||||||
|
this._dataLength += 64;
|
||||||
|
Md5._md5cycle(this._state, buf32);
|
||||||
|
bufLen -= 64;
|
||||||
|
buf32[0] = buf32[16];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._bufferLength = bufLen;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public appendAsciiStr(str: string) {
|
||||||
|
const buf8 = this._buffer8;
|
||||||
|
const buf32 = this._buffer32;
|
||||||
|
let bufLen = this._bufferLength;
|
||||||
|
let i;
|
||||||
|
let j = 0;
|
||||||
|
|
||||||
|
for (;; ) {
|
||||||
|
i = Math.min(str.length - j, 64 - bufLen);
|
||||||
|
while (i--) {
|
||||||
|
buf8[bufLen++] = str.charCodeAt(j++);
|
||||||
|
}
|
||||||
|
if (bufLen < 64) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this._dataLength += 64;
|
||||||
|
Md5._md5cycle(this._state, buf32);
|
||||||
|
bufLen = 0;
|
||||||
|
}
|
||||||
|
this._bufferLength = bufLen;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public appendByteArray(input: Uint8Array) {
|
||||||
|
const buf8 = this._buffer8;
|
||||||
|
const buf32 = this._buffer32;
|
||||||
|
let bufLen = this._bufferLength;
|
||||||
|
let i;
|
||||||
|
let j = 0;
|
||||||
|
|
||||||
|
for (;; ) {
|
||||||
|
i = Math.min(input.length - j, 64 - bufLen);
|
||||||
|
while (i--) {
|
||||||
|
buf8[bufLen++] = input[j++];
|
||||||
|
}
|
||||||
|
if (bufLen < 64) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this._dataLength += 64;
|
||||||
|
Md5._md5cycle(this._state, buf32);
|
||||||
|
bufLen = 0;
|
||||||
|
}
|
||||||
|
this._bufferLength = bufLen;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getState() {
|
||||||
|
const self = this;
|
||||||
|
const s = self._state;
|
||||||
|
|
||||||
|
return {
|
||||||
|
buffer: String.fromCharCode.apply(null, self._buffer8),
|
||||||
|
buflen: self._bufferLength,
|
||||||
|
length: self._dataLength,
|
||||||
|
state: [s[0], s[1], s[2], s[3]]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public setState(state: any) {
|
||||||
|
const buf = state.buffer;
|
||||||
|
const x = state.state;
|
||||||
|
const s = this._state;
|
||||||
|
let i;
|
||||||
|
|
||||||
|
this._dataLength = state.length;
|
||||||
|
this._bufferLength = state.buflen;
|
||||||
|
s[0] = x[0];
|
||||||
|
s[1] = x[1];
|
||||||
|
s[2] = x[2];
|
||||||
|
s[3] = x[3];
|
||||||
|
|
||||||
|
for (i = 0; i < buf.length; i += 1) {
|
||||||
|
this._buffer8[i] = buf.charCodeAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public end(raw: boolean = false) {
|
||||||
|
const bufLen = this._bufferLength;
|
||||||
|
const buf8 = this._buffer8;
|
||||||
|
const buf32 = this._buffer32;
|
||||||
|
const i = (bufLen >> 2) + 1;
|
||||||
|
let dataBitsLen;
|
||||||
|
|
||||||
|
this._dataLength += bufLen;
|
||||||
|
|
||||||
|
buf8[bufLen] = 0x80;
|
||||||
|
buf8[bufLen + 1] = buf8[bufLen + 2] = buf8[bufLen + 3] = 0;
|
||||||
|
buf32.set(Md5.buffer32Identity.subarray(i), i);
|
||||||
|
|
||||||
|
if (bufLen > 55) {
|
||||||
|
Md5._md5cycle(this._state, buf32);
|
||||||
|
buf32.set(Md5.buffer32Identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the final computation based on the tail and length
|
||||||
|
// Beware that the final length may not fit in 32 bits so we take care of that
|
||||||
|
dataBitsLen = this._dataLength * 8;
|
||||||
|
if (dataBitsLen <= 0xFFFFFFFF) {
|
||||||
|
buf32[14] = dataBitsLen;
|
||||||
|
} else {
|
||||||
|
const matches = dataBitsLen.toString(16).match(/(.*?)(.{0,8})$/);
|
||||||
|
if (matches === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lo = parseInt(matches[2], 16);
|
||||||
|
const hi = parseInt(matches[1], 16) || 0;
|
||||||
|
|
||||||
|
buf32[14] = lo;
|
||||||
|
buf32[15] = hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
Md5._md5cycle(this._state, buf32);
|
||||||
|
|
||||||
|
return raw ? this._state : Md5._hex(this._state);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/** Indicates the origin of some retrieved data. */
|
||||||
|
|
||||||
|
export enum DataSrc {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates data was probably retrieved locally from the device, although it may have been
|
||||||
|
* obtained through a content provider that may have obtained the data from a remote source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOCAL,
|
||||||
|
|
||||||
|
/** Indicates data was retrieved from a remote source other than the device. */
|
||||||
|
|
||||||
|
REMOTE,
|
||||||
|
|
||||||
|
/** Indicates data was retrieved unmodified from the on device cache. */
|
||||||
|
|
||||||
|
DATA_DISK_CACHE,
|
||||||
|
|
||||||
|
/** Indicates data was retrieved from modified content in the on device cache. */
|
||||||
|
|
||||||
|
RESOURCE_DISK_CACHE,
|
||||||
|
|
||||||
|
/** Indicates data was retrieved from the in memory cache. */
|
||||||
|
|
||||||
|
MEMORY_CACHE,
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import{DataSrc} from "../diskstrategy/DataSrc"
|
||||||
|
import{EncodeStrategy} from "../diskstrategy/EncodeStrategy"
|
||||||
|
|
||||||
|
export interface DiskStrategy {
|
||||||
|
/**
|
||||||
|
* Returns true if this request should cache the original unmodified data.
|
||||||
|
*
|
||||||
|
* @param dataSource Indicates where the data was originally retrieved.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
isDataCacheable(dataSource: DataSrc): boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this request should cache the final transformed resource.
|
||||||
|
*
|
||||||
|
* @param isFromAlternateCacheKey {@code true} if the resource we've decoded was loaded using an
|
||||||
|
* alternative, rather than the primary, cache key.
|
||||||
|
* @param dataSource Indicates where the data used to decode the resource was originally
|
||||||
|
* retrieved.
|
||||||
|
* @param encodeStrategy The {@link EncodeStrategy} the {@link
|
||||||
|
* com.bumptech.glide.load.ResourceEncoder} will use to encode the resource.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
isResourceCacheable(isFromAlternateCacheKey: boolean, dataSource: DataSrc, encodeStrategy: EncodeStrategy): boolean;
|
||||||
|
|
||||||
|
/** Returns true if this request should attempt to decode cached resource data.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
decodeCachedResource(): boolean;
|
||||||
|
|
||||||
|
/** Returns true if this request should attempt to decode cached source data.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
decodeCachedData(): boolean;
|
||||||
|
|
||||||
|
getName(): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export enum EncodeStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the original unmodified data for the resource to disk, not include downsampling or
|
||||||
|
* transformations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
SOURCE,
|
||||||
|
|
||||||
|
/** Writes the decoded, downsampled and transformed data for the resource to disk. */
|
||||||
|
|
||||||
|
TRANSFORMED,
|
||||||
|
|
||||||
|
/** Will write no data. */
|
||||||
|
|
||||||
|
NONE,
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import{DiskStrategy} from '../../diskstrategy/DiskStrategy'
|
||||||
|
import{DataSrc} from '../../diskstrategy/DataSrc'
|
||||||
|
import{EncodeStrategy} from '../../diskstrategy/EncodeStrategy'
|
||||||
|
|
||||||
|
export class ALL implements DiskStrategy {
|
||||||
|
getName(): string{
|
||||||
|
return 'ALL';
|
||||||
|
}
|
||||||
|
|
||||||
|
isDataCacheable(dataSource: DataSrc): boolean {
|
||||||
|
return dataSource == DataSrc.REMOTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isResourceCacheable(
|
||||||
|
isFromAlternateCacheKey: boolean, dataSource: DataSrc, encodeStrategy: EncodeStrategy): boolean {
|
||||||
|
return ((isFromAlternateCacheKey && dataSource == DataSrc.DATA_DISK_CACHE)
|
||||||
|
|| dataSource == DataSrc.LOCAL)
|
||||||
|
&& encodeStrategy == EncodeStrategy.TRANSFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedResource(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedData(): boolean{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import{DiskStrategy} from '../../diskstrategy/DiskStrategy'
|
||||||
|
import{DataSrc} from '../../diskstrategy/DataSrc'
|
||||||
|
import{EncodeStrategy} from '../../diskstrategy/EncodeStrategy'
|
||||||
|
|
||||||
|
export class AUTOMATIC implements DiskStrategy {
|
||||||
|
getName(): string{
|
||||||
|
return 'AUTOMATIC';
|
||||||
|
}
|
||||||
|
|
||||||
|
isDataCacheable(dataSource: DataSrc): boolean {
|
||||||
|
return dataSource == DataSrc.REMOTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isResourceCacheable(
|
||||||
|
isFromAlternateCacheKey: boolean, dataSource: DataSrc, encodeStrategy: EncodeStrategy): boolean {
|
||||||
|
return ((isFromAlternateCacheKey && dataSource == DataSrc.DATA_DISK_CACHE)
|
||||||
|
|| dataSource == DataSrc.LOCAL)
|
||||||
|
&& encodeStrategy == EncodeStrategy.TRANSFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedResource(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedData(): boolean{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import{DiskStrategy} from '../../diskstrategy/DiskStrategy'
|
||||||
|
import{DataSrc} from '../../diskstrategy/DataSrc'
|
||||||
|
import{EncodeStrategy} from '../../diskstrategy/EncodeStrategy'
|
||||||
|
|
||||||
|
export class DATA implements DiskStrategy {
|
||||||
|
getName(): string{
|
||||||
|
return 'DATA';
|
||||||
|
}
|
||||||
|
|
||||||
|
isDataCacheable(dataSource: DataSrc): boolean {
|
||||||
|
return dataSource != DataSrc.DATA_DISK_CACHE && dataSource != DataSrc.MEMORY_CACHE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isResourceCacheable(
|
||||||
|
isFromAlternateCacheKey: boolean, dataSource: DataSrc, encodeStrategy: EncodeStrategy): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedResource(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedData(): boolean{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import{DiskStrategy} from '../../diskstrategy/DiskStrategy'
|
||||||
|
import{DataSrc} from '../../diskstrategy/DataSrc'
|
||||||
|
import{EncodeStrategy} from '../../diskstrategy/EncodeStrategy'
|
||||||
|
|
||||||
|
export class NONE implements DiskStrategy {
|
||||||
|
getName(): string{
|
||||||
|
return 'NONE';
|
||||||
|
}
|
||||||
|
|
||||||
|
isDataCacheable(dataSource: DataSrc): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isResourceCacheable(
|
||||||
|
isFromAlternateCacheKey: boolean, dataSource: DataSrc, encodeStrategy: EncodeStrategy): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedResource(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedData(): boolean{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import{DiskStrategy} from '../../diskstrategy/DiskStrategy'
|
||||||
|
import{DataSrc} from '../../diskstrategy/DataSrc'
|
||||||
|
import{EncodeStrategy} from '../../diskstrategy/EncodeStrategy'
|
||||||
|
|
||||||
|
export class RESOURCE implements DiskStrategy {
|
||||||
|
getName(): string{
|
||||||
|
return 'RESOURCE';
|
||||||
|
}
|
||||||
|
|
||||||
|
isDataCacheable(dataSource: DataSrc): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isResourceCacheable(
|
||||||
|
isFromAlternateCacheKey: boolean, dataSource: DataSrc, encodeStrategy: EncodeStrategy): boolean {
|
||||||
|
return dataSource != DataSrc.RESOURCE_DISK_CACHE
|
||||||
|
&& dataSource != DataSrc.MEMORY_CACHE;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedResource(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeCachedData(): boolean{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {Key} from "../key/Key"
|
||||||
|
import {RequestOption} from '../../glide/RequestOption.ets'
|
||||||
|
|
||||||
|
export class EngineKey implements Key {
|
||||||
|
private request: RequestOption;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
request
|
||||||
|
) {
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 内存缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目
|
||||||
|
// 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图)
|
||||||
|
generateCacheKey(): string{
|
||||||
|
let loadSrc = JSON.stringify(this.request.loadSrc);
|
||||||
|
let size = JSON.stringify(this.request.size);
|
||||||
|
|
||||||
|
let transformations;
|
||||||
|
for (let i = 0; i < this.request.transformtions.length; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
transformations = this.request.transformtions[i].getName() + ",";
|
||||||
|
} else if (i == this.request.transformtions.length - 1) {
|
||||||
|
transformations += this.request.transformtions[i].getName() + "";
|
||||||
|
} else {
|
||||||
|
transformations += this.request.transformtions[i].getName() + ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag);
|
||||||
|
let key = "loadSrc=" + loadSrc + ";" +
|
||||||
|
"size=" + size + ";" +
|
||||||
|
"transformations=" + transformations + ";" +
|
||||||
|
"dontAnimateFlag=" + dontAnimateFlag + ";"
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
// 磁盘缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目
|
||||||
|
// 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图)
|
||||||
|
generateResourceKey(): string{
|
||||||
|
let loadSrc = JSON.stringify(this.request.loadSrc);
|
||||||
|
let size = JSON.stringify(this.request.size);
|
||||||
|
|
||||||
|
let transformations;
|
||||||
|
for (let i = 0; i < this.request.transformtions.length; i++) {
|
||||||
|
if (i == this.request.transformtions.length - 1) {
|
||||||
|
transformations += this.request.transformtions[i].getName() + "";
|
||||||
|
} else {
|
||||||
|
transformations += this.request.transformtions[i].getName() + ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag);
|
||||||
|
let key = "loadSrc=" + loadSrc + ";" +
|
||||||
|
"size=" + size + ";" +
|
||||||
|
"transformations=" + transformations + ";" +
|
||||||
|
"dontAnimateFlag=" + dontAnimateFlag + ";"
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 磁盘缓存
|
||||||
|
// 生成网络加载数据 原始数据存于磁盘的key
|
||||||
|
generateDataKey(): string{
|
||||||
|
let loadSrc = JSON.stringify(this.request.loadSrc);
|
||||||
|
let key = "loadSrc=" + loadSrc + ";"
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDiskCacheKey(info: Object) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {EngineKey} from '../key/EngineKey'
|
||||||
|
|
||||||
|
export class EngineKeyFactories {
|
||||||
|
buildCacheKey(
|
||||||
|
request) {
|
||||||
|
return new EngineKey(
|
||||||
|
request).generateCacheKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildDataKey(
|
||||||
|
request
|
||||||
|
) {
|
||||||
|
return new EngineKey(request).generateDataKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
buildResourceKey(
|
||||||
|
request
|
||||||
|
) {
|
||||||
|
return new EngineKey(request).generateResourceKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
export interface Key {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all uniquely identifying information to the given digest.
|
||||||
|
*
|
||||||
|
* <p>Note - Using {@link MessageDigest#reset()} inside of this method will result
|
||||||
|
* in undefined behavior.
|
||||||
|
* @param messageDigest
|
||||||
|
*/
|
||||||
|
updateDiskCacheKey(info: Object);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,407 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {DiskLruCache} from "../cache/DiskLruCache"
|
||||||
|
import {LruCache} from "../cache/LruCache"
|
||||||
|
import {EngineKey} from "../cache/key/EngineKey"
|
||||||
|
import {EngineKeyFactories} from "../cache/key/EngineKeyFactories"
|
||||||
|
import {DiskStrategy} from "../cache/diskstrategy/DiskStrategy"
|
||||||
|
import {ResourceTypeEts} from "../glide/constants/ResourceTypeEts.ets"
|
||||||
|
import {RequestOption} from "../glide/RequestOption.ets"
|
||||||
|
import {AsyncCallback} from "../glide/interface/asynccallback.ets"
|
||||||
|
import {PlaceHolderManager} from "../glide/holder/PlaceHolderManager.ets"
|
||||||
|
import {ErrorHolderManager} from "../glide/holder/ErrorHolderManager.ets"
|
||||||
|
import {RequestManager} from "../glide/requestmanage/RequstManager.ets"
|
||||||
|
import {NONE} from "../cache/diskstrategy/enum/NONE"
|
||||||
|
import {FileTypeUtil} from '../glide/utils/FileTypeUtil.ets'
|
||||||
|
import {DownloadClient} from '../glide/networkmanage/DownloadClient.ets'
|
||||||
|
import {IDataFetch} from '../glide/networkmanage/IDataFetch.ets'
|
||||||
|
import {ParseResClient} from '../glide/resourcemanage/ParseResClient.ets'
|
||||||
|
import {IResourceFetch} from '../glide/resourcemanage/IResourceFetch.ets'
|
||||||
|
import {GlideData} from '../glide/GlideData.ets'
|
||||||
|
import {FileUtils} from '../cache/FileUtils.ets'
|
||||||
|
import {FileReader} from '../cache/FileReader.ets'
|
||||||
|
import {GlideOption} from '../glide/GlideOption.ets'
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
import featureAbility from '@ohos.ability.featureAbility';
|
||||||
|
import {CompressBuilder} from "../glide/compress/CompressBuilder.ets"
|
||||||
|
|
||||||
|
export class Glide {
|
||||||
|
private memoryCache: LruCache<string, any>;
|
||||||
|
private diskMemoryCache: DiskLruCache;
|
||||||
|
private dataFetch: IDataFetch;
|
||||||
|
private resourceFetch: IResourceFetch;
|
||||||
|
private filesPath: string = ""; // data/data/包名/files目录
|
||||||
|
|
||||||
|
|
||||||
|
private placeholderCache: string = "placeholderCache"
|
||||||
|
private runningRequest: Array<RequestOption>;
|
||||||
|
private pendingRequest: Array<RequestOption>;
|
||||||
|
private fileTypeUtil: FileTypeUtil; // 通用文件格式辨别
|
||||||
|
private svgAndGifFolder: string = "svgAndGifFolder"; // svg和gif的文件路径地址
|
||||||
|
private svgAndGifCommitFile: string = "svgAndGifCommitFile" // svg和gif提交记录
|
||||||
|
|
||||||
|
private defaultListener:AsyncCallback<GlideData>; // 全局监听器
|
||||||
|
|
||||||
|
getMemoryCache(): LruCache<string, any>{
|
||||||
|
return this.memoryCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMemoryCache(lrucache: LruCache<string, any>){
|
||||||
|
this.memoryCache = lrucache;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDiskMemoryCache(): DiskLruCache{
|
||||||
|
return this.diskMemoryCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
setDiskMemoryCache(diskLruCache: DiskLruCache) {
|
||||||
|
this.diskMemoryCache = diskLruCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
getFileTypeUtil(): FileTypeUtil{
|
||||||
|
return this.fileTypeUtil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getSvgAndGifFolder(): string{
|
||||||
|
return this.svgAndGifFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSvgAndGifFolder(folderPath: string){
|
||||||
|
this.svgAndGifFolder = folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultListener(){
|
||||||
|
return this.defaultListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultListener(newDefaultListener:AsyncCallback<GlideData>){
|
||||||
|
this.defaultListener = newDefaultListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
|
||||||
|
// 构造方法传入size 为保存文件个数
|
||||||
|
this.memoryCache = new LruCache<string, any>(100);
|
||||||
|
|
||||||
|
// 创建disk缓存 传入的size 为多少比特 比如20KB 传入20*1024
|
||||||
|
this.diskMemoryCache = new DiskLruCache(30 * 1024 * 1024);
|
||||||
|
|
||||||
|
// 创建网络下载能力
|
||||||
|
this.dataFetch = new DownloadClient();
|
||||||
|
|
||||||
|
// 创建本地数据解析能力
|
||||||
|
this.resourceFetch = new ParseResClient();
|
||||||
|
|
||||||
|
// 初始化本地 文件保存
|
||||||
|
featureAbility.getContext()
|
||||||
|
.getFilesDir()
|
||||||
|
.then((data) => {
|
||||||
|
this.filesPath = data
|
||||||
|
this.initSvgAndGifEnvironment();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Glide Failed to obtain the filesPath directory. Cause:' + error.message);
|
||||||
|
})
|
||||||
|
|
||||||
|
this.runningRequest = new Array();
|
||||||
|
this.pendingRequest = new Array();
|
||||||
|
|
||||||
|
// 通用文件格式识别初始化
|
||||||
|
this.fileTypeUtil = new FileTypeUtil();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initSvgAndGifEnvironment() {
|
||||||
|
let folderExist = FileUtils.getInstance().existFolder(this.filesPath + "/" + this.svgAndGifFolder)
|
||||||
|
let fileExist =
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.exist(this.filesPath + "/" + this.svgAndGifFolder + "/" + this.svgAndGifCommitFile)
|
||||||
|
if (folderExist && fileExist) {
|
||||||
|
// 创建完成,需要删除上次使用的文件
|
||||||
|
var fileReader = new FileReader(this.filesPath + "/" + this.svgAndGifFolder + "/" + this.svgAndGifCommitFile)
|
||||||
|
var line: string = ''
|
||||||
|
while (!fileReader.isEnd()) {
|
||||||
|
line = fileReader.readLine()
|
||||||
|
line = line.replace('\n', "").replace('\r', "")
|
||||||
|
FileUtils.getInstance().deleteFile(this.filesPath + "/" + this.svgAndGifFolder + "/" + line)
|
||||||
|
}
|
||||||
|
FileUtils.getInstance().clearFile(this.filesPath + "/" + this.svgAndGifFolder + "/" + this.svgAndGifCommitFile)
|
||||||
|
} else {
|
||||||
|
if (!folderExist) {
|
||||||
|
FileUtils.getInstance().createFolder(this.filesPath + "/" + this.svgAndGifFolder);
|
||||||
|
}
|
||||||
|
if (!fileExist) {
|
||||||
|
FileUtils.getInstance().createFile(this.filesPath + "/" + this.svgAndGifFolder + "/" + this.svgAndGifCommitFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static sInstance: Glide;
|
||||||
|
|
||||||
|
public static with(): Glide{
|
||||||
|
if (!this.sInstance) {
|
||||||
|
this.sInstance = new Glide();
|
||||||
|
}
|
||||||
|
return this.sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public compressBuilder(): CompressBuilder{
|
||||||
|
return new CompressBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替代原来的LruCache
|
||||||
|
public replaceLruCache(size:number){
|
||||||
|
if(this.memoryCache.map.size() <= 0) {
|
||||||
|
this.memoryCache = new LruCache<string, any>(size);
|
||||||
|
}else{
|
||||||
|
let newLruCache = new LruCache<string, any>(size);
|
||||||
|
this.memoryCache.foreachLruCache(function (value, key, map) {
|
||||||
|
newLruCache.put(key, value);
|
||||||
|
})
|
||||||
|
this.memoryCache = newLruCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public replaceDataFetch(fetch:IDataFetch){
|
||||||
|
this.dataFetch = fetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替代原来的DiskLruCache
|
||||||
|
public replaceDiskLruCache(size:number){
|
||||||
|
this.diskMemoryCache = new DiskLruCache(size);
|
||||||
|
|
||||||
|
if(this.diskMemoryCache.cacheMap.size() <= 0) {
|
||||||
|
this.diskMemoryCache = new DiskLruCache(size);
|
||||||
|
}else{
|
||||||
|
let newDiskLruCache = new DiskLruCache(size);
|
||||||
|
this.diskMemoryCache.foreachDiskLruCache(function (value, key, map) {
|
||||||
|
newDiskLruCache.putCacheData(key, value, null);
|
||||||
|
})
|
||||||
|
this.diskMemoryCache = newDiskLruCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预加载 resource资源一级缓存,string资源实现二级缓存
|
||||||
|
preload(request: RequestOption) {
|
||||||
|
// 每个request 公共信息补充
|
||||||
|
request.setFilesPath(this.filesPath);
|
||||||
|
// svg特殊处理
|
||||||
|
request._svgAndGifFolder = this.svgAndGifFolder;
|
||||||
|
request._svgAndGifCommitFile = this.svgAndGifCommitFile;
|
||||||
|
return this.parseSource(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正常加载
|
||||||
|
call(request: RequestOption) {
|
||||||
|
console.log("Glide call")
|
||||||
|
// 添加全局监听
|
||||||
|
if(this.defaultListener) {
|
||||||
|
request.addListener(this.defaultListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每个request 公共信息补充
|
||||||
|
request.setFilesPath(this.filesPath);
|
||||||
|
|
||||||
|
// svg特殊处理
|
||||||
|
request._svgAndGifFolder = this.svgAndGifFolder;
|
||||||
|
request._svgAndGifCommitFile = this.svgAndGifCommitFile;
|
||||||
|
|
||||||
|
// 首先执行占位图 解析任务
|
||||||
|
if (request.placeholderSrc) {
|
||||||
|
PlaceHolderManager.execute(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其次解析错误占位图
|
||||||
|
if (request.errorholderSrc) {
|
||||||
|
ErrorHolderManager.execute(request)
|
||||||
|
}
|
||||||
|
return this.parseSource(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadResources(request: RequestOption) {
|
||||||
|
console.log("Glide loadResources")
|
||||||
|
let factories = new EngineKeyFactories();
|
||||||
|
|
||||||
|
// 生成内存缓存key 内存 变换后磁盘
|
||||||
|
let cacheKey = factories.buildCacheKey(request);
|
||||||
|
|
||||||
|
// 生成磁盘缓存变换后数据key 变换后数据保存在磁盘
|
||||||
|
let transfromKey = factories.buildResourceKey(request);
|
||||||
|
|
||||||
|
// 生成磁盘缓存源数据key 原始数据保存在磁盘
|
||||||
|
let dataKey = factories.buildDataKey(request);
|
||||||
|
|
||||||
|
request.generateCacheKey = cacheKey;
|
||||||
|
request.generateResourceKey = transfromKey;
|
||||||
|
request.generateDataKey = dataKey;
|
||||||
|
this.loadCacheManager(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除执行结束的running
|
||||||
|
removeRunning(request: RequestOption) {
|
||||||
|
let index = -1;
|
||||||
|
for (let i = 0; i < this.runningRequest.length; i++) {
|
||||||
|
let tempRunning = this.runningRequest[i];
|
||||||
|
if (this.keyEqual(request, tempRunning)) {
|
||||||
|
// 如果key相同 说明目前有任务正在执行,我们记录下当前request 放入pendingRunning
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index >= 0) {
|
||||||
|
let request = this.runningRequest.splice(index, 1)[0];
|
||||||
|
this.loadNextPennding(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyEqualPendingToRun(index:number){
|
||||||
|
let nextPending = this.pendingRequest.splice(index, 1)[0];
|
||||||
|
this.runningRequest.push(nextPending)
|
||||||
|
RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||||
|
}
|
||||||
|
|
||||||
|
searchNextKeyToRun(){
|
||||||
|
// 其次则寻找pending中第一个和running不重复的key
|
||||||
|
let index2 = -1;
|
||||||
|
for (let i = 0; i < this.pendingRequest.length; i++) {
|
||||||
|
let temppending = this.pendingRequest[i];
|
||||||
|
let hasKeyEqual = false;
|
||||||
|
for (let j = 0; j < this.runningRequest.length; j++) {
|
||||||
|
let temprunning = this.runningRequest[j];
|
||||||
|
if (this.keyEqual(temppending, temprunning)) {
|
||||||
|
hasKeyEqual = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasKeyEqual) {
|
||||||
|
index2 = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index2 >= 0) {
|
||||||
|
let nextPending = this.pendingRequest.splice(index2, 1)[0];
|
||||||
|
this.runningRequest.push(nextPending)
|
||||||
|
RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||||
|
} else {
|
||||||
|
// 不执行
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 加载下一个key的请求
|
||||||
|
loadNextPennding(request) {
|
||||||
|
// 首先寻找被移除key相同的request
|
||||||
|
let index = -1;
|
||||||
|
for (let i = 0; i < this.pendingRequest.length; i++) {
|
||||||
|
let temppending = this.pendingRequest[i];
|
||||||
|
if (this.keyEqual(request, temppending)) {
|
||||||
|
// 如果key相同 说明目前有任务正在执行,我们记录下当前request 放入pendingRunning
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index >= 0) {
|
||||||
|
this.keyEqualPendingToRun(index);
|
||||||
|
} else {
|
||||||
|
this.searchNextKeyToRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动新线程 去磁盘取 去网络取
|
||||||
|
loadCacheManager(request: RequestOption) {
|
||||||
|
console.log("Glide loadCacheManager")
|
||||||
|
if (this.keyNotEmpty(request)) {
|
||||||
|
let hasRunningRequest = false;
|
||||||
|
for (let i = 0; i < this.runningRequest.length; i++) {
|
||||||
|
let tempRunning = this.runningRequest[i];
|
||||||
|
if (this.keyEqual(request, tempRunning)) {
|
||||||
|
|
||||||
|
// 如果key相同 说明目前有任务正在执行,我们记录下当前request 放入pendingRunning
|
||||||
|
hasRunningRequest = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasRunningRequest) {
|
||||||
|
this.pendingRequest.push(request);
|
||||||
|
} else {
|
||||||
|
this.runningRequest.push(request);
|
||||||
|
|
||||||
|
// 不存在相同key的 任务可以并行
|
||||||
|
RequestManager.execute(request, this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("key没有生成无法进入存取!")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private keyNotEmpty(request: RequestOption): boolean{
|
||||||
|
if (
|
||||||
|
request.generateCacheKey != null && request.generateCacheKey.length > 0 &&
|
||||||
|
request.generateDataKey != null && request.generateDataKey.length > 0 &&
|
||||||
|
request.generateResourceKey != null && request.generateResourceKey.length > 0
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private keyEqual(request1: RequestOption, request2: RequestOption): boolean{
|
||||||
|
if (
|
||||||
|
request1.generateCacheKey == request2.generateCacheKey &&
|
||||||
|
request1.generateResourceKey == request2.generateResourceKey &&
|
||||||
|
request1.generateDataKey == request2.generateDataKey
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseSource(request: RequestOption) {
|
||||||
|
console.log("Glide parseSource")
|
||||||
|
console.log("Glide request ="+JSON.stringify(request))
|
||||||
|
if (request.loadSrc instanceof image.PixelMap) {
|
||||||
|
console.log("Glide parseSource PixelMap")
|
||||||
|
let glidedata = new GlideData();
|
||||||
|
glidedata.glideType = GlideData.PIXELMAP
|
||||||
|
glidedata.glideValue = request.loadSrc as PixelMap
|
||||||
|
request.loadComplete(glidedata);
|
||||||
|
} else
|
||||||
|
if (typeof request.loadSrc == 'string') {
|
||||||
|
// 进入三级缓存模型
|
||||||
|
console.log("Glide parseSource string")
|
||||||
|
return this.loadResources(request);
|
||||||
|
} else {
|
||||||
|
console.log("Glide parseSource Resource")
|
||||||
|
let res = request.loadSrc as Resource;
|
||||||
|
console.log("Glide parseSource res="+JSON.stringify(res))
|
||||||
|
if (typeof res.id != 'undefined' && typeof res.type != 'undefined') {
|
||||||
|
//进入三级缓存模型 本地资源不参与磁盘缓存
|
||||||
|
let none = new NONE();
|
||||||
|
request.diskCacheStrategy(none);
|
||||||
|
this.loadResources(request);
|
||||||
|
} else {
|
||||||
|
console.error("输入参数有问题!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class GlideData {
|
||||||
|
|
||||||
|
static PIXELMAP = 'PixelMap'
|
||||||
|
static STRING = 'string'
|
||||||
|
static RESOURCE ='Resource'
|
||||||
|
|
||||||
|
static SVG = 'svg';
|
||||||
|
static GIF = 'gif';
|
||||||
|
static JPG = 'jpg';
|
||||||
|
static PNG = 'png';
|
||||||
|
static BMP = 'bmp';
|
||||||
|
static WEBP = 'webp';
|
||||||
|
|
||||||
|
|
||||||
|
glideType:string = '';
|
||||||
|
glideValue:PixelMap|string|Resource;
|
||||||
|
glideSourceType:string = ''
|
||||||
|
|
||||||
|
isSvg():boolean{
|
||||||
|
return GlideData.SVG == this.glideSourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
isGif():boolean{
|
||||||
|
return GlideData.GIF == this.glideSourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
isJpg():boolean{
|
||||||
|
return GlideData.JPG == this.glideSourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
isPng():boolean{
|
||||||
|
return GlideData.PNG == this.glideSourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBmp():boolean{
|
||||||
|
return GlideData.BMP == this.glideSourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
isWebp():boolean{
|
||||||
|
return GlideData.WEBP == this.glideSourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isString():boolean{
|
||||||
|
return GlideData.STRING == this.glideType;
|
||||||
|
}
|
||||||
|
isPixelMap():boolean{
|
||||||
|
return GlideData.PIXELMAP == this.glideType;
|
||||||
|
}
|
||||||
|
isResource():boolean{
|
||||||
|
return GlideData.RESOURCE == this.glideType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
can2PixelMap(){ // 可以转换为PixelMap的数据源
|
||||||
|
return this.isPixelMap() || this.isBmp() || this.isJpg() || this.isWebp() || this.isPng();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,303 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {GlideOption} from '../glide/GlideOption.ets'
|
||||||
|
import {RequestOption} from '../glide/RequestOption.ets'
|
||||||
|
import {GlideData} from '../glide/GlideData.ets'
|
||||||
|
import {PixelMapPack} from '../glide/PixelMapPack.ets'
|
||||||
|
import {Base64} from '../cache/Base64.ets'
|
||||||
|
import resourceManager from '@ohos.resourceManager';
|
||||||
|
import image from '@ohos.multimedia.image';
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export struct GlideImage {
|
||||||
|
@Watch('watchGlideOption') @Link glideOption: GlideOption;
|
||||||
|
@State glidePixelMapPack: PixelMapPack = new PixelMapPack();
|
||||||
|
@State glideResource: Resource = $r('app.media.icon_loading')
|
||||||
|
@State glideString: string = ''
|
||||||
|
@State normalPixelMap: boolean = true;
|
||||||
|
@State normalResource: boolean = true;
|
||||||
|
previousData: GlideData = null;
|
||||||
|
nowData: GlideData = null;
|
||||||
|
@State percentVisible: Visibility = Visibility.Visible
|
||||||
|
@State retryVisible: Visibility = Visibility.Visible
|
||||||
|
@State imageVisible: Visibility = Visibility.Visible
|
||||||
|
@State percent: string = '0%'
|
||||||
|
@State percentWidth: string = '0%';
|
||||||
|
@State percentHeight: string = '0%';
|
||||||
|
@State retryWidth: string = '0%';
|
||||||
|
@State retryHeight: string = '0%';
|
||||||
|
@State imageWidth: string = '100%';
|
||||||
|
@State imageHeight: string = '100%';
|
||||||
|
|
||||||
|
hasRetry:boolean = false;
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Stack() {
|
||||||
|
|
||||||
|
Text(this.percent)
|
||||||
|
.fontSize(this.glideOption.size ? Math.min(this.glideOption.size.height, this.glideOption.size.width) / 2 : 24)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
.visibility(this.retryVisible)
|
||||||
|
.width(this.percentWidth)
|
||||||
|
.height(this.percentHeight)
|
||||||
|
|
||||||
|
Image($r('app.media.icon_retry'))
|
||||||
|
.onClick(()=>{
|
||||||
|
this.retryClick();
|
||||||
|
})
|
||||||
|
.visibility(this.retryVisible)
|
||||||
|
.width(this.retryWidth)
|
||||||
|
.height(this.retryHeight)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Image(this.normalPixelMap ? this.glidePixelMapPack.pixelMap : (this.normalResource ? this.glideResource : this.glideString))
|
||||||
|
.objectFit(this.glideOption.imageFit ? this.glideOption.imageFit : ImageFit.Fill)
|
||||||
|
.visibility(this.imageVisible)
|
||||||
|
.width(this.imageWidth)
|
||||||
|
.height(this.imageHeight)
|
||||||
|
}
|
||||||
|
.width(this.glideOption.size ? this.glideOption.size.width : '100%')
|
||||||
|
.height(this.glideOption.size ? this.glideOption.size.height : '100%')
|
||||||
|
.backgroundColor(this.glideOption.backgroundColor ? this.glideOption.backgroundColor : Color.White)
|
||||||
|
.margin(this.glideOption.margin ? this.glideOption.margin : { left: 0, top: 0, right: 0, bottom: 0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
watchGlideOption() {
|
||||||
|
this.glideExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
retryClick(){
|
||||||
|
this.hasRetry = true;
|
||||||
|
this.glideExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToAppear() {
|
||||||
|
console.log('glideImage aboutToAppear happened!')
|
||||||
|
this.glideExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
configNecessary(request: RequestOption){
|
||||||
|
// 为了测试重试加载 串讲完成后删除
|
||||||
|
if(this.glideOption.loadSrc == 'https://hbimg.huabanimg.com/testRetryxxxx' && this.hasRetry){
|
||||||
|
request.load('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp')
|
||||||
|
.addListener((err, data) => {
|
||||||
|
this.glideChangeSource(data)
|
||||||
|
this.animateTo('image');
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
}else {
|
||||||
|
|
||||||
|
request.load(this.glideOption.loadSrc)
|
||||||
|
.addListener((err, data) => {
|
||||||
|
this.glideChangeSource(data)
|
||||||
|
this.animateTo('image');
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.glideOption.size) {
|
||||||
|
request.setImageViewSize(this.glideOption.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configCacheStrategy(request: RequestOption){
|
||||||
|
if (this.glideOption.onlyRetrieveFromCache) {
|
||||||
|
request.retrieveDataFromCache(this.glideOption.onlyRetrieveFromCache)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.glideOption.isCacheable) {
|
||||||
|
request.skipMemoryCache(!this.glideOption.isCacheable)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.glideOption.strategy) {
|
||||||
|
request.diskCacheStrategy(this.glideOption.strategy)
|
||||||
|
}
|
||||||
|
if (this.glideOption.allCacheInfoCallback) {
|
||||||
|
request.addAllCacheInfoCallback(this.glideOption.allCacheInfoCallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configDisplay(request: RequestOption){
|
||||||
|
if(this.glideOption.animateDuration >= 0){
|
||||||
|
request.animateDuraction = this.glideOption.animateDuration;
|
||||||
|
}
|
||||||
|
if (this.glideOption.placeholderSrc) {
|
||||||
|
request.placeholder(this.glideOption.placeholderSrc, (data) => {
|
||||||
|
this.glideChangeSource(data)
|
||||||
|
this.animateTo('image');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this.glideOption.thumbSizeMultiplier) {
|
||||||
|
request.thumbnail(this.glideOption.thumbSizeMultiplier, (data) => {
|
||||||
|
this.glideChangeSource(data)
|
||||||
|
this.animateTo('image');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this.glideOption.errorholderSrc) {
|
||||||
|
request.errorholder(this.glideOption.errorholderSrc, (data) => {
|
||||||
|
this.glideChangeSource(data)
|
||||||
|
this.animateTo('image');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this.glideOption.transformtions) {
|
||||||
|
request.transforms(this.glideOption.transformtions)
|
||||||
|
}
|
||||||
|
if (this.glideOption.dontAnimateFlag) {
|
||||||
|
request.dontAnimate()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (this.glideOption.displayProgress) {
|
||||||
|
request.addProgressListener((percentValue: string) => {
|
||||||
|
// 如果进度条百分比 未展示大小,展示其动画
|
||||||
|
this.percent = percentValue;
|
||||||
|
if(this.glideOption.displayProgressListener){
|
||||||
|
this.glideOption.displayProgressListener(percentValue);
|
||||||
|
}
|
||||||
|
this.animateTo('progress');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.glideOption.retryLoad){
|
||||||
|
request.addRetryListener((error: any) => {
|
||||||
|
console.log("RetryListener callback!")
|
||||||
|
this.animateTo('retry');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// glide 第一次启动和数据刷新后重新发送请求
|
||||||
|
glideExecute() {
|
||||||
|
let request = new RequestOption();
|
||||||
|
this.configNecessary(request);
|
||||||
|
this.configCacheStrategy(request);
|
||||||
|
this.configDisplay(request);
|
||||||
|
let svgGif = Glide.getSvgAndGifFolder();
|
||||||
|
console.log("输出SVG和gif的缓存地址="+svgGif)
|
||||||
|
console.log("GlideImage Ready to 'call' method! Glide is null="+(Glide == null || Glide == undefined))
|
||||||
|
Glide.call(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
glideChangeSource(data:GlideData) {
|
||||||
|
this.glideSpecialFixed(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
displayPixelMap(data:GlideData){
|
||||||
|
|
||||||
|
this.normalPixelMap = true;
|
||||||
|
this.normalResource = true;
|
||||||
|
let pack = new PixelMapPack();
|
||||||
|
this.glidePixelMapPack = pack;
|
||||||
|
setTimeout(() => {
|
||||||
|
let pixelMapPack2 = new PixelMapPack();
|
||||||
|
pixelMapPack2.pixelMap = data.glideValue as PixelMap;
|
||||||
|
this.glidePixelMapPack = pixelMapPack2;
|
||||||
|
},100)
|
||||||
|
}
|
||||||
|
|
||||||
|
displayResource(data:GlideData){
|
||||||
|
this.normalPixelMap = false;
|
||||||
|
this.normalResource = true;
|
||||||
|
this.glideResource = data.glideValue as Resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
displayString(data:GlideData){
|
||||||
|
|
||||||
|
this.normalPixelMap = false;
|
||||||
|
this.normalResource = false;
|
||||||
|
let firstIndex = (data.glideValue as string).indexOf(Glide.getSvgAndGifFolder());
|
||||||
|
let suffix = (data.glideValue as string).substring(firstIndex, (data.glideValue as string).length)
|
||||||
|
// let glideNeedStr = 'internal://app/' + suffix;
|
||||||
|
let glideNeedStr = 'file://' + data.glideValue;
|
||||||
|
this.glideString = glideNeedStr;
|
||||||
|
|
||||||
|
}
|
||||||
|
glideSpecialFixed(data:GlideData) {
|
||||||
|
if (data.isPixelMap()) {
|
||||||
|
this.displayPixelMap(data);
|
||||||
|
}
|
||||||
|
else if (data.isString()) {
|
||||||
|
this.displayString(data);
|
||||||
|
} else if (data.isResource()) {
|
||||||
|
this.displayResource(data);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animateTo(name: string) {
|
||||||
|
if (name == 'progress') {
|
||||||
|
this.percentVisible = Visibility.Visible;
|
||||||
|
this.imageVisible = Visibility.Hidden;
|
||||||
|
this.retryVisible = Visibility.Hidden;
|
||||||
|
if (this.percentWidth == '0%' || this.percentHeight == '0%') {
|
||||||
|
animateTo({ duration: this.glideOption.animateDuration , curve: Curve.Linear }, () => {
|
||||||
|
this.percentWidth = '100%';
|
||||||
|
this.percentHeight = '100%';
|
||||||
|
this.imageWidth = '0%';
|
||||||
|
this.imageHeight = '0%';
|
||||||
|
this.retryWidth = '0%';
|
||||||
|
this.retryHeight = '0%';
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (name == 'image') {
|
||||||
|
this.imageVisible = Visibility.Visible;
|
||||||
|
this.percentVisible = Visibility.Hidden;
|
||||||
|
this.retryVisible = Visibility.Hidden;
|
||||||
|
if (this.imageWidth == '0%' || this.imageHeight == '0%') {
|
||||||
|
animateTo({ duration: this.glideOption.animateDuration, curve: Curve.Linear }, () => {
|
||||||
|
this.imageWidth = '100%';
|
||||||
|
this.imageHeight = '100%';
|
||||||
|
this.percentWidth = '0%';
|
||||||
|
this.percentHeight = '0%';
|
||||||
|
this.retryWidth = '0%';
|
||||||
|
this.retryHeight = '0%';
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (name == 'retry') {
|
||||||
|
this.retryVisible = Visibility.Visible;
|
||||||
|
this.imageVisible = Visibility.Hidden;
|
||||||
|
this.percentVisible = Visibility.Hidden;
|
||||||
|
if (this.retryWidth == '0%' || this.retryHeight == '0%') {
|
||||||
|
animateTo({ duration: this.glideOption.animateDuration, curve: Curve.Linear }, () => {
|
||||||
|
this.imageWidth = '0%';
|
||||||
|
this.imageHeight = '0%';
|
||||||
|
this.percentWidth = '0%';
|
||||||
|
this.percentHeight = '0%';
|
||||||
|
this.retryWidth = '100%';
|
||||||
|
this.retryHeight = '100%';
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToDisappear() {
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageShow() {
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageHide() {
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackPress() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var Glide;
|
||||||
|
var defaultTemp = globalThis.exports.default
|
||||||
|
if (defaultTemp != undefined) {
|
||||||
|
Glide = defaultTemp.data.glide;
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {AUTOMATIC} from "../cache/diskstrategy/enum/AUTOMATIC.ets"
|
||||||
|
import {DiskStrategy} from "../cache/diskstrategy/DiskStrategy.ets"
|
||||||
|
import {BaseTransform} from "../glide/transform/BaseTransform.ets"
|
||||||
|
import {AllCacheInfo, IAllCacheInfoCallback} from "../glide/interface/iallcacheinfocallback.ets"
|
||||||
|
|
||||||
|
export class GlideOption {
|
||||||
|
|
||||||
|
// 主图资源
|
||||||
|
loadSrc: string | PixelMap | Resource;
|
||||||
|
|
||||||
|
// 磁盘缓存策略
|
||||||
|
strategy?: DiskStrategy = new AUTOMATIC();
|
||||||
|
|
||||||
|
// gif加载展示一帧
|
||||||
|
dontAnimateFlag? = false;
|
||||||
|
|
||||||
|
// 占位图
|
||||||
|
placeholderSrc?: PixelMap | Resource;
|
||||||
|
|
||||||
|
// 失败占位图
|
||||||
|
errorholderSrc?: PixelMap | Resource;
|
||||||
|
|
||||||
|
// 缩略图,范围(0,1)
|
||||||
|
thumbSizeMultiplier?: number;
|
||||||
|
|
||||||
|
// 进度条
|
||||||
|
displayProgress?: boolean;
|
||||||
|
|
||||||
|
// 进度条回调
|
||||||
|
displayProgressListener?;
|
||||||
|
|
||||||
|
// 重试图层
|
||||||
|
retryLoad?: boolean;
|
||||||
|
|
||||||
|
// 动画时长
|
||||||
|
animateDuration?: number = 500;
|
||||||
|
|
||||||
|
// 仅使用缓存加载数据
|
||||||
|
onlyRetrieveFromCache?: boolean = false;
|
||||||
|
|
||||||
|
// 是否开启第一级内存缓存
|
||||||
|
isCacheable?: boolean = true;
|
||||||
|
|
||||||
|
// 变换相关
|
||||||
|
transformtions?: Array<BaseTransform<PixelMap>> = new Array();
|
||||||
|
|
||||||
|
// 输出缓存相关内容和信息
|
||||||
|
allCacheInfoCallback?: IAllCacheInfoCallback;
|
||||||
|
size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
};
|
||||||
|
imageFit?: ImageFit;
|
||||||
|
backgroundColor?: Color | number | string | Resource;
|
||||||
|
margin?: {
|
||||||
|
top?: number | string | Resource,
|
||||||
|
right?: number | string | Resource,
|
||||||
|
bottom?: number | string | Resource,
|
||||||
|
left?: number | string | Resource
|
||||||
|
} | number | string | Resource
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class PixelMapPack {
|
||||||
|
pixelMap:PixelMap
|
||||||
|
}
|
|
@ -0,0 +1,294 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {DiskStrategy} from "../cache/diskstrategy/DiskStrategy"
|
||||||
|
import {AsyncCallback} from "../glide/interface/asynccallback.ets"
|
||||||
|
import {AsyncSuccess} from "../glide/interface/AsyncSuccess.ets"
|
||||||
|
import {AllCacheInfo, IAllCacheInfoCallback} from "../glide/interface/iallcacheinfocallback.ets"
|
||||||
|
import {AUTOMATIC} from "../cache/diskstrategy/enum/AUTOMATIC"
|
||||||
|
import {BaseTransform} from "../glide/transform/BaseTransform.ets"
|
||||||
|
import {RotateImageTransformation} from "../glide/transform/RotateImageTransformation.ets"
|
||||||
|
import {GlideData} from "../glide/GlideData.ets"
|
||||||
|
import fileio from '@ohos.fileio';
|
||||||
|
import image from '@ohos.multimedia.image';
|
||||||
|
import {CenterCrop} from '../glide/transform/pixelmap/CenterCrop.ets'
|
||||||
|
import {CenterInside} from '../glide/transform/pixelmap/CenterInside.ets'
|
||||||
|
import {FitCenter} from '../glide/transform/pixelmap/FitCenter.ets'
|
||||||
|
|
||||||
|
export class RequestOption {
|
||||||
|
loadSrc: string | PixelMap | Resource;
|
||||||
|
strategy: DiskStrategy = new AUTOMATIC();
|
||||||
|
dontAnimateFlag = false;
|
||||||
|
placeholderSrc: PixelMap | Resource;
|
||||||
|
placeholderFunc: AsyncSuccess<GlideData>;
|
||||||
|
errorholderSrc: PixelMap | Resource;
|
||||||
|
errorholderFunc: AsyncSuccess<GlideData>;
|
||||||
|
errorholderData: GlideData;
|
||||||
|
thumbSizeMultiplier: number;
|
||||||
|
|
||||||
|
// 如果存在缩略图,则主图延时3000ms加载
|
||||||
|
thumbDelayTime: number = 3000
|
||||||
|
thumbholderFunc: AsyncSuccess<GlideData>;
|
||||||
|
requestListeners: Array<AsyncCallback<GlideData>>;
|
||||||
|
|
||||||
|
// 进度条
|
||||||
|
progressFunc: AsyncSuccess<string>;
|
||||||
|
|
||||||
|
// 重试图层
|
||||||
|
retryFunc: AsyncSuccess<GlideData>
|
||||||
|
|
||||||
|
// 图层切换时长
|
||||||
|
animateDuraction: number = 500;
|
||||||
|
size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
} = { width: -1, height: -1 };
|
||||||
|
|
||||||
|
// 网络下载数据回调
|
||||||
|
allCacheInfoCallback: IAllCacheInfoCallback;
|
||||||
|
onlyRetrieveFromCache: boolean = false;
|
||||||
|
isCacheable: boolean = true;
|
||||||
|
|
||||||
|
// 变换相关
|
||||||
|
transformtions: Array<BaseTransform<PixelMap>> = new Array();
|
||||||
|
generateCacheKey: string = "";
|
||||||
|
generateResourceKey: string = "";
|
||||||
|
generateDataKey: string = "";
|
||||||
|
private filesPath: string = ""; // data/data/包名/files目录
|
||||||
|
private cachesPath: string = ""; // 网络下载默认存储在data/data/包名/cache/GlideNetworkFolder/目标md5.img下面
|
||||||
|
|
||||||
|
// 下载原始文件地址
|
||||||
|
downloadFilePath: string = "";
|
||||||
|
|
||||||
|
// 网络文件下载统一存放
|
||||||
|
networkCacheFolder: string = "GlideNetworkFolder"
|
||||||
|
|
||||||
|
|
||||||
|
// 主线图片 状态变化 是否加载完成
|
||||||
|
// 主图未加载成功 显示占位图 主图加载成功不展示占位图
|
||||||
|
loadMainReady = false;
|
||||||
|
|
||||||
|
// 失败占位图展示状态 当true 表示主图加载失败需要展示失败占位图
|
||||||
|
loadErrorReady = false
|
||||||
|
|
||||||
|
// 缩略图展示
|
||||||
|
loadThumbnailReady = false;
|
||||||
|
_svgAndGifFolder: string = "svgAndGifFolder"; // svg和gif的文件路径地址
|
||||||
|
_svgAndGifCommitFile: string = "svgAndGifCommitFile"; // svg和gif提交记录
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// 初始化全局监听
|
||||||
|
this.requestListeners = new Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set image Component size
|
||||||
|
*/
|
||||||
|
setImageViewSize(imageSize: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) {
|
||||||
|
this.size.width = imageSize.width;
|
||||||
|
this.size.height = imageSize.height;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFilesPath() {
|
||||||
|
return this.filesPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilesPath(path: string) {
|
||||||
|
this.filesPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCachesPath() {
|
||||||
|
return this.cachesPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCachesPath(path: string) {
|
||||||
|
this.cachesPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
load(src: string | PixelMap | Resource) {
|
||||||
|
this.loadSrc = src;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
diskCacheStrategy(strategy: DiskStrategy) {
|
||||||
|
this.strategy = strategy;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
dontAnimate() {
|
||||||
|
this.dontAnimateFlag = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 仅支持 本地图片
|
||||||
|
placeholder(src: PixelMap | Resource, func?: AsyncSuccess<GlideData>) {
|
||||||
|
this.placeholderSrc = src;
|
||||||
|
this.placeholderFunc = func;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorholder(src: PixelMap | Resource, func?: AsyncSuccess<GlideData>) {
|
||||||
|
this.errorholderSrc = src;
|
||||||
|
this.errorholderFunc = func;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
thumbnail(sizeMultiplier: number, func?: AsyncSuccess<GlideData>) {
|
||||||
|
this.thumbSizeMultiplier = sizeMultiplier;
|
||||||
|
this.thumbholderFunc = func;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addProgressListener(func?: AsyncSuccess<string>) {
|
||||||
|
this.progressFunc = func;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addRetryListener(func?: AsyncSuccess<any>) {
|
||||||
|
this.retryFunc = func;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener(func: AsyncCallback<GlideData>) {
|
||||||
|
this.requestListeners.push(func);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addAllCacheInfoCallback(func: IAllCacheInfoCallback) {
|
||||||
|
this.allCacheInfoCallback = func;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
skipMemoryCache(skip: boolean) {
|
||||||
|
this.isCacheable = !skip;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
retrieveDataFromCache(flag: boolean) {
|
||||||
|
this.onlyRetrieveFromCache = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
rotateImage(degreesToRotate: number) {
|
||||||
|
let rotateImage = new RotateImageTransformation(degreesToRotate);
|
||||||
|
this.transformtions.push(rotateImage);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
centerCrop() {
|
||||||
|
this.transformtions.push(new CenterCrop());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
centerInside() {
|
||||||
|
this.transformtions.push(new CenterInside());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
fitCenter() {
|
||||||
|
this.transformtions.push(new FitCenter());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(transform: BaseTransform<PixelMap>) {
|
||||||
|
this.transformtions.push(transform);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
transforms(transforms: BaseTransform<PixelMap>[]) {
|
||||||
|
this.transformtions = transforms;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 占位图解析成功
|
||||||
|
placeholderOnComplete(glidedata: GlideData) {
|
||||||
|
console.log("placeholderOnComplete has called!");
|
||||||
|
console.log("Main Image is Ready:" + this.loadMainReady);
|
||||||
|
if (!this.loadMainReady && !this.loadErrorReady && !this.loadThumbnailReady) {
|
||||||
|
// 主图未加载成功,并且未加载失败 显示占位图 主图加载成功或者加载失败后=>不展示占位图
|
||||||
|
this.placeholderFunc(glidedata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 占位图解析失败
|
||||||
|
placeholderOnError(error) {
|
||||||
|
console.log("占位图解析失败 error =" + error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缩略图解析成功
|
||||||
|
thumbholderOnComplete(glidedata: GlideData) {
|
||||||
|
if (!this.loadMainReady && !this.loadErrorReady) {
|
||||||
|
//主图未加载成功,并且未加载失败 显示占位图 主图加载成功或者加载失败后=>不展示占位图
|
||||||
|
this.thumbholderFunc(glidedata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缩略图解析失败
|
||||||
|
thumbholderOnError(error) {
|
||||||
|
console.log("缩略图解析失败 error =" + error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载失败 占位图解析成功
|
||||||
|
errorholderOnComplete(glidedata: GlideData) {
|
||||||
|
// 如果有错误占位图 先解析并保存在RequestOption中 等到加载失败时候进行调用
|
||||||
|
this.errorholderData = glidedata;
|
||||||
|
if (this.loadErrorReady) {
|
||||||
|
this.errorholderFunc(glidedata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//加载失败 占位图解析失败
|
||||||
|
errorholderOnError(error) {
|
||||||
|
console.log("失败占位图解析失败 error =" + error)
|
||||||
|
}
|
||||||
|
|
||||||
|
loadComplete(glidedata: GlideData) {
|
||||||
|
this.loadMainReady = true;
|
||||||
|
// 三级缓存数据加载成功
|
||||||
|
for (let requestListener of this.requestListeners) {
|
||||||
|
var ret = requestListener("", glidedata);
|
||||||
|
if (ret) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 加载成功之后
|
||||||
|
Glide.removeRunning(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadError(err) {
|
||||||
|
console.log("loadError:"+err);
|
||||||
|
//失败占位图展示规则
|
||||||
|
this.loadErrorReady = true;
|
||||||
|
if (this.retryFunc) {
|
||||||
|
// 重试图层优先于加载失败展示
|
||||||
|
this.retryFunc(err)
|
||||||
|
} else {
|
||||||
|
if (this.errorholderData != null) {
|
||||||
|
this.errorholderFunc(this.errorholderData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载失败之后
|
||||||
|
Glide.removeRunning(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var Glide;
|
||||||
|
var defaultTemp = globalThis.exports.default
|
||||||
|
if (defaultTemp != undefined) {
|
||||||
|
Glide = defaultTemp.data.glide;
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {OnRenameListener} from '../compress/listener/OnRenameListener.ets'
|
||||||
|
import {OnCompressListener} from '../compress/listener/OnCompressListener.ets'
|
||||||
|
import {CompressionPredicate} from '../compress/listener/CompressionPredicate.ets'
|
||||||
|
import fileio from '@ohos.fileio';
|
||||||
|
import {CompressAdapter} from '../compress/provider/CompressAdapter.ets'
|
||||||
|
import {DataStringPathProvider} from '../compress/provider/DataStringPathProvider.ets'
|
||||||
|
import {RecourseProvider} from '../compress/provider/RecourseProvider.ets'
|
||||||
|
import featureability from '@ohos.ability.featureAbility'
|
||||||
|
import {Engine} from '../compress/Engine.ets'
|
||||||
|
|
||||||
|
export class CompressBuilder {
|
||||||
|
private _mTargetDir: string;
|
||||||
|
private _mLeastCompressSize: number= 100; //KB
|
||||||
|
private _mRenameListener: OnRenameListener;
|
||||||
|
private _mCompressListener: OnCompressListener;
|
||||||
|
private _mCompressionPredicate: CompressionPredicate
|
||||||
|
private _mStreamProviders: Array<CompressAdapter>;
|
||||||
|
private _mFocusAlpha: boolean;
|
||||||
|
private _outFilePath: string;
|
||||||
|
constructor() {
|
||||||
|
this._mStreamProviders = new Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setRenameListener(listener: OnRenameListener): CompressBuilder {
|
||||||
|
this._mRenameListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setCompressListener(listener: OnCompressListener): CompressBuilder {
|
||||||
|
this._mCompressListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public filter(compressionPredicate: CompressionPredicate): CompressBuilder {
|
||||||
|
this._mCompressionPredicate = compressionPredicate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setTargetDir(targetDir: string): CompressBuilder {
|
||||||
|
this._mTargetDir = targetDir;
|
||||||
|
if (this._mTargetDir) {
|
||||||
|
var timestamp = (new Date()).valueOf();
|
||||||
|
this._outFilePath = this._mTargetDir + "/" + timestamp + (Math.random() * 100).toFixed(0) + ".jpg";
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public load(list: Array<string | Resource>): CompressBuilder {
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
let element = list[i];
|
||||||
|
if (typeof element === "string") {
|
||||||
|
this.loadString(element);
|
||||||
|
} else {
|
||||||
|
this.loadRecourse(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load string file path;
|
||||||
|
*/
|
||||||
|
private loadString(path: string) {
|
||||||
|
this._mStreamProviders.push(new DataStringPathProvider(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load resource;
|
||||||
|
*/
|
||||||
|
private loadRecourse(data: Resource) {
|
||||||
|
this._mStreamProviders.push(new RecourseProvider(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public setFocusAlpha(focusAlpha: boolean): CompressBuilder {
|
||||||
|
this._mFocusAlpha = focusAlpha;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ignoreBy(size: number): CompressBuilder {
|
||||||
|
this._mLeastCompressSize = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public launch() {
|
||||||
|
if (!this._mTargetDir) {
|
||||||
|
this.getImageCacheFile();
|
||||||
|
} else {
|
||||||
|
this.startCompress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async get():Promise<string> {
|
||||||
|
if (!this._mTargetDir) {
|
||||||
|
let path = await featureability.getContext().getFilesDir();
|
||||||
|
var timestamp = (new Date()).valueOf();
|
||||||
|
this._outFilePath = path + "/compress/" + timestamp + (Math.random() * 100).toFixed(0) + ".jpg";
|
||||||
|
let result =await this.startAsyncCompress();
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
let result =await this.startAsyncCompress();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async startAsyncCompress():Promise<string> {
|
||||||
|
let compressPromise = new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
let compressListener: OnCompressListener = {
|
||||||
|
start() {
|
||||||
|
},
|
||||||
|
onScuccess(p: PixelMap, path: string) {
|
||||||
|
resolve(path);
|
||||||
|
},
|
||||||
|
onError(s: string) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compressListener.start();
|
||||||
|
|
||||||
|
if (this._mStreamProviders == null || this._mStreamProviders.length == 0) {
|
||||||
|
compressListener.onError("this compress path is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < this._mStreamProviders.length; i++) {
|
||||||
|
let element = this._mStreamProviders[i];
|
||||||
|
let isOpenfilter = false;
|
||||||
|
if (this._mCompressionPredicate) {
|
||||||
|
isOpenfilter = this._mCompressionPredicate.apply(element.getRecoursePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!isOpenfilter) {
|
||||||
|
new Engine(element, this._outFilePath, this._mFocusAlpha, this._mLeastCompressSize,
|
||||||
|
compressListener, this._mCompressionPredicate).compress();
|
||||||
|
} else {
|
||||||
|
resolve(element.getRecoursePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
let result = await compressPromise
|
||||||
|
return (result as string)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start compress
|
||||||
|
*/
|
||||||
|
private startCompress() {
|
||||||
|
if (this._mStreamProviders == null || this._mStreamProviders.length == 0) {
|
||||||
|
if (this._mCompressListener) {
|
||||||
|
this._mCompressListener.onError("this compress path is empty");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._mRenameListener) {
|
||||||
|
var name = this._mRenameListener.reName();
|
||||||
|
if (this._outFilePath && name) {
|
||||||
|
var start = this._outFilePath.lastIndexOf("/") + 1
|
||||||
|
var end = this._outFilePath.length;
|
||||||
|
var replaceStr = this._outFilePath.substring(start, end);
|
||||||
|
this._outFilePath = this._outFilePath.replace(replaceStr, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._mCompressListener) {
|
||||||
|
this._mCompressListener.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < this._mStreamProviders.length; i++) {
|
||||||
|
let element = this._mStreamProviders[i];
|
||||||
|
let isOpenfilter = false;
|
||||||
|
if (this._mCompressionPredicate) {
|
||||||
|
isOpenfilter = this._mCompressionPredicate.apply(element.getRecoursePath());
|
||||||
|
}
|
||||||
|
if (!isOpenfilter) {
|
||||||
|
new Engine(element, this._outFilePath, this._mFocusAlpha, this._mLeastCompressSize,
|
||||||
|
this._mCompressListener, this._mCompressionPredicate).compress();
|
||||||
|
} else {
|
||||||
|
if (this._mCompressListener) {
|
||||||
|
this._mCompressListener.onScuccess(null, element.getRecoursePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getImageCacheFile() {
|
||||||
|
featureability.getContext()
|
||||||
|
.getFilesDir()
|
||||||
|
.then(path => {
|
||||||
|
var timestamp = (new Date()).valueOf();
|
||||||
|
this._outFilePath = path + "/compress/" + timestamp + (Math.random() * 100).toFixed(0) + ".jpg";
|
||||||
|
this.startCompress();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
throw new Error("getImageCacheFile happened error:" + JSON.stringify(error));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {OnCompressListener} from '../compress/listener/OnCompressListener.ets'
|
||||||
|
import {CompressionPredicate} from '../compress/listener/CompressionPredicate.ets'
|
||||||
|
import {CompressAdapter} from "../compress/provider/CompressAdapter.ets"
|
||||||
|
import {DataStringPathProvider} from '../compress/provider/DataStringPathProvider.ets'
|
||||||
|
import {RecourseProvider} from '../compress/provider/RecourseProvider.ets'
|
||||||
|
import {FileUtils} from '../../cache/FileUtils'
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
import fileio from '@ohos.fileio';
|
||||||
|
|
||||||
|
export class Engine {
|
||||||
|
private mFocusAlpha: boolean;
|
||||||
|
private mCompressListener: OnCompressListener
|
||||||
|
private mPredicate: CompressionPredicate
|
||||||
|
private mCompressAdapter: CompressAdapter
|
||||||
|
private mPath: string
|
||||||
|
private _mLeastCompressSize: number; //KB
|
||||||
|
|
||||||
|
constructor(compressAdapter: CompressAdapter,
|
||||||
|
outPath: string,
|
||||||
|
focusAlpha: boolean,
|
||||||
|
leastSize: number,
|
||||||
|
compressListener: OnCompressListener,
|
||||||
|
predicate: CompressionPredicate) {
|
||||||
|
this.mCompressAdapter = compressAdapter;
|
||||||
|
this.mPath = outPath;
|
||||||
|
this.mFocusAlpha = focusAlpha;
|
||||||
|
this.mCompressListener = compressListener;
|
||||||
|
this.mPredicate = predicate;
|
||||||
|
this._mLeastCompressSize = leastSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private computeSize(srcWidth: number, srcHeight: number): number {
|
||||||
|
srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
|
||||||
|
srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;
|
||||||
|
|
||||||
|
var longSide = Math.max(srcWidth, srcHeight);
|
||||||
|
var shortSide = Math.min(srcWidth, srcHeight);
|
||||||
|
|
||||||
|
var scale = shortSide / longSide;
|
||||||
|
if (scale <= 1 && scale > 0.5625) {
|
||||||
|
if (longSide < 1664) {
|
||||||
|
return 1;
|
||||||
|
} else if (longSide < 4990) {
|
||||||
|
return 2;
|
||||||
|
} else if (longSide > 4990 && longSide < 10240) {
|
||||||
|
return 4;
|
||||||
|
} else {
|
||||||
|
return longSide / 1280 == 0 ? 1 : longSide / 1280;
|
||||||
|
}
|
||||||
|
} else if (scale <= 0.5625 && scale > 0.5) {
|
||||||
|
return longSide / 1280 == 0 ? 1 : longSide / 1280;
|
||||||
|
} else {
|
||||||
|
return Math.ceil(longSide / (1280.0 / scale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compress() {
|
||||||
|
console.info("asasd compress()")
|
||||||
|
if (this.mCompressAdapter instanceof DataStringPathProvider) {
|
||||||
|
// file
|
||||||
|
this.mCompressAdapter.openInternal((buffer) => {
|
||||||
|
if (!buffer) {
|
||||||
|
if (this.mCompressListener) {
|
||||||
|
this.mCompressListener.onError("file read fail,and date is empty")
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.checkNeedCompress(buffer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageResource = image.createImageSource(buffer);
|
||||||
|
imageResource.getImageInfo()
|
||||||
|
.then(info => {
|
||||||
|
var height = info.size.height;
|
||||||
|
var width = info.size.width;
|
||||||
|
var computeSize = this.computeSize(width, height);
|
||||||
|
console.info("asasd compress computeSize:" + computeSize);
|
||||||
|
let options = {
|
||||||
|
editable: true,
|
||||||
|
sampleSize: computeSize,
|
||||||
|
desiredPixelFormat: image.PixelMapFormat.RGB_565,
|
||||||
|
}
|
||||||
|
imageResource.createPixelMap(options)
|
||||||
|
.then(bitmap => {
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.mCompressListener.onError("ptah createPixelMap fail,because error:" + JSON.stringify(error))
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.mCompressListener.onError("ptah getImageInfo fail,because error:" + JSON.stringify(error))
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
} else if (this.mCompressAdapter instanceof RecourseProvider) {
|
||||||
|
// resource
|
||||||
|
this.mCompressAdapter.openInternal((buffer) => {
|
||||||
|
if (!buffer) {
|
||||||
|
if (this.mCompressListener) {
|
||||||
|
this.mCompressListener.onError("resource read fail,and date is empty")
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.checkNeedCompress(buffer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageResource = image.createImageSource(buffer);
|
||||||
|
imageResource.getImageInfo()
|
||||||
|
.then(info => {
|
||||||
|
var height = info.size.height;
|
||||||
|
var width = info.size.width;
|
||||||
|
var computeSize = this.computeSize(width, height);
|
||||||
|
let packer = {
|
||||||
|
format: ["image/jpeg"],
|
||||||
|
quality: computeSize,
|
||||||
|
}
|
||||||
|
var imagePacker = image.createImagePacker();
|
||||||
|
imagePacker.packing(imageResource, packer, (err,compressBuffer)=>{
|
||||||
|
if(err){
|
||||||
|
this.mCompressListener.onError("resource packing fail,because error:" + err);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("compressBuffer is null ="+ (compressBuffer==null));
|
||||||
|
console.log("compressBuffer is undefined ="+ (compressBuffer == undefined) );
|
||||||
|
let dirPath = this.mPath.substring(0, this.mPath.lastIndexOf("/") + 1);
|
||||||
|
var isDirectory = this.checkDirExist(dirPath);
|
||||||
|
if (isDirectory) {
|
||||||
|
this.saveFile(this.mPath, compressBuffer);
|
||||||
|
this.handResult(compressBuffer, this.mPath);
|
||||||
|
} else {
|
||||||
|
fileio.mkdir(dirPath)
|
||||||
|
.then(() => {
|
||||||
|
this.saveFile(this.mPath, compressBuffer);
|
||||||
|
this.handResult(compressBuffer, this.mPath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handResult(buffer: ArrayBuffer, path: string) {
|
||||||
|
var imageRes = image.createImageSource(buffer);
|
||||||
|
let a={
|
||||||
|
editable: true,
|
||||||
|
}
|
||||||
|
imageRes.createPixelMap(a)
|
||||||
|
.then(bitmap => {
|
||||||
|
if (this.mCompressListener) {
|
||||||
|
this.mCompressListener.onScuccess(bitmap, path);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
if (this.mCompressListener) {
|
||||||
|
this.mCompressListener.onError("buffer generated pixelMap fail,because error:" + JSON.stringify(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkNeedCompress(buf: ArrayBuffer): boolean{
|
||||||
|
if (!buf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var length = buf.byteLength / 1024;
|
||||||
|
return length > this._mLeastCompressSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private saveFile(path: string, content: ArrayBuffer) {
|
||||||
|
FileUtils.getInstance().writeFile(path,content);
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkDirExist(dirPath: string): boolean{
|
||||||
|
var isExist;
|
||||||
|
try {
|
||||||
|
fileio.accessSync(dirPath, 0)
|
||||||
|
isExist = true;
|
||||||
|
} catch (e) {
|
||||||
|
//不符合条件则进入
|
||||||
|
isExist = false;
|
||||||
|
}
|
||||||
|
return isExist;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface CompressDataListener<T> {
|
||||||
|
(t: T);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* filter out unsupported
|
||||||
|
*/
|
||||||
|
export interface CompressionPredicate {
|
||||||
|
apply(path: string): boolean;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* compress listener
|
||||||
|
*/
|
||||||
|
export interface OnCompressListener {
|
||||||
|
/**
|
||||||
|
* compress start
|
||||||
|
*/
|
||||||
|
start();
|
||||||
|
/**
|
||||||
|
* compress success
|
||||||
|
*/
|
||||||
|
onScuccess(p: PixelMap, path: string);
|
||||||
|
/**
|
||||||
|
* compress fail
|
||||||
|
*/
|
||||||
|
onError(s: string);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rename listener
|
||||||
|
*/
|
||||||
|
export interface OnRenameListener {
|
||||||
|
reName():string;
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {CompressProvider} from "../provider/CompressProvider.ets"
|
||||||
|
import {CompressDataListener} from "../listener/CompressDataListener.ets"
|
||||||
|
|
||||||
|
export abstract class CompressAdapter implements CompressProvider {
|
||||||
|
mData: ArrayBuffer;
|
||||||
|
mPath: string;
|
||||||
|
|
||||||
|
close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
openData(): ArrayBuffer{
|
||||||
|
return this.mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPath(): string{
|
||||||
|
return this.mPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract openInternal(callback: CompressDataListener<ArrayBuffer>);
|
||||||
|
|
||||||
|
abstract getRecoursePath(): string;
|
||||||
|
|
||||||
|
abstract getPixelMapFormat(): PixelMapFormat;
|
||||||
|
|
||||||
|
getFormat(s: string): PixelMapFormat{
|
||||||
|
if (!s) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (s == "jpg" || s == "JPG") {
|
||||||
|
return PixelMapFormat.JPG;
|
||||||
|
} else if (s == "png" || s == "PNG") {
|
||||||
|
return PixelMapFormat.PNG;
|
||||||
|
} else if (s == "jpeg" || s == "JPEG") {
|
||||||
|
return PixelMapFormat.JPEG;
|
||||||
|
} else if (s == "gif" || s == "GIF") {
|
||||||
|
return PixelMapFormat.GIF;
|
||||||
|
} else if (s == "webp" || s == "WEBP" || s == "WebP") {
|
||||||
|
return PixelMapFormat.WEBP;
|
||||||
|
} else if (s == "bmg" || s == "BMG") {
|
||||||
|
return PixelMapFormat.BMG;
|
||||||
|
} else {
|
||||||
|
return PixelMapFormat.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PixelMapFormat {
|
||||||
|
JPG,
|
||||||
|
PNG,
|
||||||
|
JPEG,
|
||||||
|
WEBP,
|
||||||
|
BMG,
|
||||||
|
GIF,
|
||||||
|
NONE
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface CompressProvider {
|
||||||
|
close();
|
||||||
|
|
||||||
|
openData():ArrayBuffer;
|
||||||
|
|
||||||
|
getPath(): string;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {CompressAdapter, PixelMapFormat} from '../provider/CompressAdapter.ets'
|
||||||
|
import {CompressDataListener} from '../listener/CompressDataListener.ets'
|
||||||
|
import {FileUtils} from '../../../cache/FileUtils.ets'
|
||||||
|
|
||||||
|
export class DataStringPathProvider extends CompressAdapter {
|
||||||
|
constructor(s: string) {
|
||||||
|
super()
|
||||||
|
this.mPath = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecoursePath(): string{
|
||||||
|
return this.mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
openInternal(callback: CompressDataListener<ArrayBuffer>) {
|
||||||
|
if (!this.mPath) {
|
||||||
|
throw new Error('DataStringPathProvider error path is empty');
|
||||||
|
}
|
||||||
|
var buffer = FileUtils.getInstance().readFilePic(this.mPath);
|
||||||
|
this.mData = buffer;
|
||||||
|
if (callback) {
|
||||||
|
callback(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPixelMapFormat(): PixelMapFormat{
|
||||||
|
if (!this.mPath) {
|
||||||
|
return PixelMapFormat.NONE;
|
||||||
|
}
|
||||||
|
let lastIndex = this.mPath.lastIndexOf('/')
|
||||||
|
let s = this.mPath.substring(lastIndex + 1, this.mPath.length);
|
||||||
|
return this.getFormat(s);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {CompressAdapter, PixelMapFormat} from "../provider/CompressAdapter.ets"
|
||||||
|
import resmgr from '@ohos.resourceManager'
|
||||||
|
import {CompressDataListener} from "../listener/CompressDataListener.ets"
|
||||||
|
import {FileTypeUtil} from '../../../glide/utils/FileTypeUtil.ets'
|
||||||
|
|
||||||
|
export class RecourseProvider extends CompressAdapter {
|
||||||
|
private static CHARS: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
private static DEFAULT_RESOURCE_PATH: string= "Resource"
|
||||||
|
private _mLookup: Uint8Array = new Uint8Array(256);
|
||||||
|
private _mResourceData: Resource;
|
||||||
|
private _mPixelMapHeader: string;
|
||||||
|
|
||||||
|
constructor(s: Resource) {
|
||||||
|
super()
|
||||||
|
this._mResourceData = s;
|
||||||
|
this.mPath = RecourseProvider.DEFAULT_RESOURCE_PATH;
|
||||||
|
for (var index = 0; index < RecourseProvider.CHARS.length; index++) {
|
||||||
|
this._mLookup[RecourseProvider.CHARS.charCodeAt(index)] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecoursePath(): string{
|
||||||
|
return this.mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
openInternal(callback: CompressDataListener<ArrayBuffer>) {
|
||||||
|
console.info("asasd compress openInternal _mData");
|
||||||
|
if (!this._mResourceData) {
|
||||||
|
throw Error("compress resource is empty");
|
||||||
|
}
|
||||||
|
resmgr.getResourceManager()
|
||||||
|
.then(result => {
|
||||||
|
result.getMedia(this._mResourceData
|
||||||
|
.id)
|
||||||
|
.then(data => {
|
||||||
|
let buffer = this.uint8ArrayToBuffer(data);
|
||||||
|
let fileTypeUtil = new FileTypeUtil()
|
||||||
|
this._mPixelMapHeader = fileTypeUtil.getFileType(buffer);
|
||||||
|
callback(buffer);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log("RecourseProvider openInternal err" + JSON.stringify(err));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getPixelMapFormat(): PixelMapFormat{
|
||||||
|
if (!this._mPixelMapHeader) {
|
||||||
|
return PixelMapFormat.NONE;
|
||||||
|
}
|
||||||
|
return this.getFormat(this._mPixelMapHeader);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* data decode
|
||||||
|
*/
|
||||||
|
decode(base64: string, callback: CompressDataListener<ArrayBuffer>) {
|
||||||
|
let bufferLength = base64.length,
|
||||||
|
len = base64.length,
|
||||||
|
i,
|
||||||
|
p = 0,
|
||||||
|
encoded1,
|
||||||
|
encoded2,
|
||||||
|
encoded3,
|
||||||
|
encoded4;
|
||||||
|
|
||||||
|
if (base64[base64.length - 1] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
if (base64[base64.length - 2] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const arraybuffer = new ArrayBuffer(bufferLength),
|
||||||
|
bytes = new Uint8Array(arraybuffer);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 4) {
|
||||||
|
encoded1 = this._mLookup[base64.charCodeAt(i)];
|
||||||
|
encoded2 = this._mLookup[base64.charCodeAt(i + 1)];
|
||||||
|
encoded3 = this._mLookup[base64.charCodeAt(i + 2)];
|
||||||
|
encoded4 = this._mLookup[base64.charCodeAt(i + 3)];
|
||||||
|
|
||||||
|
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
||||||
|
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
||||||
|
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
||||||
|
|
||||||
|
}
|
||||||
|
this.mData = arraybuffer;
|
||||||
|
if (callback) {
|
||||||
|
callback(arraybuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8ArrayToBuffer(array: Uint8Array): ArrayBuffer {
|
||||||
|
return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class Constants {
|
||||||
|
public static PROJECT_TAG: string= "Glide_js"
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export enum ResourceTypeEts {
|
||||||
|
COLOR = 10001,
|
||||||
|
FLOAT,
|
||||||
|
STRING,
|
||||||
|
PLURAL,
|
||||||
|
BOOLEAN,
|
||||||
|
INTARRAY,
|
||||||
|
INTEGER,
|
||||||
|
PATTERN,
|
||||||
|
STRARRAY,
|
||||||
|
MEDIA = 20000,
|
||||||
|
RAWFILE = 30000
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
|
||||||
|
export namespace Crop {
|
||||||
|
|
||||||
|
export function crop(buf: ArrayBuffer, x: number, y: number, cropWidth: number, cropHeight: number, func?: AsyncTransform<PixelMap>, colorRatio?: number) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log("Crop buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func("Crop buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
if (x < 0 || x > pixelMapWidth) {
|
||||||
|
func("Crop error x must be less than pixelMapWidth ", null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > pixelMapHeight) {
|
||||||
|
func("Crop error x must be less than pixelMapHeight ", null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
rotate: 0,
|
||||||
|
desiredSize: {
|
||||||
|
width: pixelMapWidth,
|
||||||
|
height: pixelMapHeight
|
||||||
|
},
|
||||||
|
desiredRegion: { size: { width: cropWidth, height: cropHeight },
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((data) => {
|
||||||
|
if (colorRatio && colorRatio <= 1) {
|
||||||
|
colorRatioPixelMap(data, pixelMapWidth, pixelMapHeight, colorRatio, func);
|
||||||
|
} else {
|
||||||
|
func("", data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
func(e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function colorRatioPixelMap(data: any, width: number, height: number, colorRatio: number, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!data) {
|
||||||
|
func("colorRatio pixelMap is null", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (colorRatio > 1) {
|
||||||
|
throw new Error("the colorRatio must be <= 1");
|
||||||
|
}
|
||||||
|
var buffer = new ArrayBuffer(width * height * 5);
|
||||||
|
var bytes = new Uint8Array(buffer);
|
||||||
|
var buffer1B = new ArrayBuffer(width * height * 5);
|
||||||
|
var bytes1B = new Uint8Array(buffer1B);
|
||||||
|
|
||||||
|
let readPromise = data.readPixelsToBuffer(buffer)
|
||||||
|
await readPromise;
|
||||||
|
for (let i = 0;i < bytes.length; i++) {
|
||||||
|
bytes1B[i] = bytes[i] * colorRatio;
|
||||||
|
}
|
||||||
|
let writePromise = data.writeBufferToPixels(buffer1B)
|
||||||
|
await writePromise;
|
||||||
|
func("", data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {CropOptions} from "../crop/CropOptions.ets";
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export struct CropImage {
|
||||||
|
@Link _mOptions: CropOptions;
|
||||||
|
@State _rotate: number= 0;
|
||||||
|
@State _scale: number= 1;
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Stack() {
|
||||||
|
Image(this._mOptions.src)
|
||||||
|
.width(this._mOptions.size.width)
|
||||||
|
.height(this._mOptions.size.height)
|
||||||
|
.objectFit(ImageFit.None)
|
||||||
|
.rotate({
|
||||||
|
z: 1,
|
||||||
|
centerX: this._mOptions.size.width / 2,
|
||||||
|
centerY: this._mOptions.size.height / 2,
|
||||||
|
angle: this._rotate
|
||||||
|
})
|
||||||
|
.scale({ x: this._scale, y: this._scale, z: 1.0 })
|
||||||
|
.gesture(GestureGroup(GestureMode.Parallel,
|
||||||
|
RotationGesture({ fingers: 1 }).onActionUpdate(event => {
|
||||||
|
this._rotate = event.angle;
|
||||||
|
}), PinchGesture({ fingers: 2 }).onActionUpdate(event => {
|
||||||
|
this._scale = event.scale;
|
||||||
|
})
|
||||||
|
).onCancel(() => {
|
||||||
|
console.log("CropImage gesture cancel");
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}.width(this._mOptions.size.width).height(this._mOptions.size.height);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class CropOptions {
|
||||||
|
src: string | PixelMap | Resource;
|
||||||
|
size: {
|
||||||
|
width: number,
|
||||||
|
height: number;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class ArcPoint {
|
||||||
|
private x: number;
|
||||||
|
private y: number;
|
||||||
|
|
||||||
|
constructor(x: number, y: number) {
|
||||||
|
this.y = y;
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
getX(): number{
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
getY(): number{
|
||||||
|
return this.y
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
export class PixelEntry {
|
||||||
|
a: number;
|
||||||
|
b: number;
|
||||||
|
r: number;
|
||||||
|
g: number;
|
||||||
|
f: number;
|
||||||
|
pixel: number;
|
||||||
|
|
||||||
|
public toString(): string {
|
||||||
|
return "PixelEntry a:" + this.a + ";b:" + this.b + ";r:" + this.r + ";g:" + this.g + ";f:" + this.f;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {FileTypeUtil} from "../../glide/utils/FileTypeUtil.ets"
|
||||||
|
import {GlideData} from "../GlideData.ets"
|
||||||
|
import {ParseImageUtil} from '../utils/ParseImageUtil.ets'
|
||||||
|
import {ParseResClient} from '../resourcemanage/ParseResClient.ets'
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class ErrorHolderManager {
|
||||||
|
private options: RequestOption;
|
||||||
|
|
||||||
|
constructor(option: RequestOption) {
|
||||||
|
this.options = option;
|
||||||
|
}
|
||||||
|
|
||||||
|
static execute(option: RequestOption) {
|
||||||
|
let manager = new ErrorHolderManager(option);
|
||||||
|
return new Promise(manager.process.bind(manager))
|
||||||
|
.then(option.errorholderOnComplete.bind(option)).catch(option.errorholderOnError.bind(option));
|
||||||
|
}
|
||||||
|
|
||||||
|
process(onComplete, onError) {
|
||||||
|
this.displayErrorholder(onComplete, onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private displayErrorholder(onComplete, onError) {
|
||||||
|
console.log("displayErrorholder")
|
||||||
|
if (this.options.errorholderSrc instanceof image.PixelMap) {
|
||||||
|
let glidedata = new GlideData();
|
||||||
|
glidedata.glideType = GlideData.PIXELMAP
|
||||||
|
glidedata.glideValue = this.options.placeholderSrc as PixelMap
|
||||||
|
onComplete(glidedata);
|
||||||
|
} else if (typeof this.options.errorholderSrc == 'string') {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
let res = this.options.errorholderSrc as Resource;
|
||||||
|
if (typeof res.id != 'undefined' && typeof res.id != 'undefined') {
|
||||||
|
let resourceFetch = new ParseResClient();
|
||||||
|
let suc = (arraybuffer) => {
|
||||||
|
let fileTypeUtil = new FileTypeUtil();
|
||||||
|
let typeValue = fileTypeUtil.getFileType(arraybuffer);
|
||||||
|
if ("gif" == typeValue || "svg" == typeValue) {
|
||||||
|
let glidedata = new GlideData();
|
||||||
|
glidedata.glideType = "Resource"
|
||||||
|
glidedata.glideValue = this.options.errorholderSrc as Resource
|
||||||
|
glidedata.glideSourceType = typeValue;
|
||||||
|
onComplete(glidedata);
|
||||||
|
} else {
|
||||||
|
let parseImageUtils = new ParseImageUtil();
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
let glidedata = new GlideData();
|
||||||
|
glidedata.glideType = "PixelMap"
|
||||||
|
glidedata.glideValue = value
|
||||||
|
glidedata.glideSourceType = typeValue;
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
parseImageUtils.parseImage(arraybuffer, success, onError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resourceFetch.loadResource(res, suc, onError)
|
||||||
|
} else {
|
||||||
|
onError("ErrorHolderManager 输入参数有问题!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {ResourceTypeEts} from "../../glide/constants/ResourceTypeEts.ets"
|
||||||
|
import {Base64} from "../../cache/Base64.ets"
|
||||||
|
import {FileTypeUtil} from "../../glide/utils/FileTypeUtil.ets"
|
||||||
|
import {GlideData} from "../GlideData.ets"
|
||||||
|
import {ParseImageUtil} from '../utils/ParseImageUtil.ets'
|
||||||
|
import {ParseResClient} from '../resourcemanage/ParseResClient.ets'
|
||||||
|
import resourceManager from '@ohos.resourceManager';
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class PlaceHolderManager {
|
||||||
|
private options: RequestOption;
|
||||||
|
|
||||||
|
constructor(option: RequestOption) {
|
||||||
|
this.options = option;
|
||||||
|
}
|
||||||
|
|
||||||
|
static execute(option: RequestOption) {
|
||||||
|
let manager = new PlaceHolderManager(option);
|
||||||
|
return new Promise(manager.process.bind(manager))
|
||||||
|
.then(option.placeholderOnComplete.bind(option)).catch(option.placeholderOnError.bind(option));
|
||||||
|
}
|
||||||
|
|
||||||
|
process(onComplete, onError) {
|
||||||
|
this.displayPlaceholder(onComplete, onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private displayPlaceholder(onComplete, onError) {
|
||||||
|
console.log("displayPlaceholder")
|
||||||
|
if (this.options.placeholderSrc instanceof image.PixelMap) {
|
||||||
|
let glidedata = new GlideData();
|
||||||
|
glidedata.glideType = GlideData.PIXELMAP
|
||||||
|
glidedata.glideValue = this.options.placeholderSrc as PixelMap
|
||||||
|
onComplete(glidedata);
|
||||||
|
} else if (typeof this.options.placeholderSrc == 'string') {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
let res = this.options.placeholderSrc as Resource;
|
||||||
|
if (typeof res.id != 'undefined' && typeof res.id != 'undefined') {
|
||||||
|
let resourceFetch = new ParseResClient();
|
||||||
|
let suc = (arraybuffer) => {
|
||||||
|
let fileTypeUtil = new FileTypeUtil();
|
||||||
|
let typeValue = fileTypeUtil.getFileType(arraybuffer);
|
||||||
|
if ("gif" == typeValue || "svg" == typeValue) {
|
||||||
|
let glidedata = this.createGlideData("Resource", this.options.placeholderSrc as Resource, typeValue);
|
||||||
|
onComplete(glidedata);
|
||||||
|
} else {
|
||||||
|
let parseImageUtils = new ParseImageUtil();
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData('PixelMap', value, typeValue);
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
parseImageUtils.parseImage(arraybuffer, success, onError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resourceFetch.loadResource(res, suc, onError)
|
||||||
|
} else {
|
||||||
|
onError("PlaceHolderManager 输入参数有问题!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private createGlideData(glideType:string, glideValue:PixelMap|string|Resource, glideSourceType:string):GlideData{
|
||||||
|
let glidedata = new GlideData();
|
||||||
|
glidedata.glideType = glideType;
|
||||||
|
glidedata.glideValue = glideValue;
|
||||||
|
glidedata.glideSourceType = glideSourceType;
|
||||||
|
return glidedata;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface AsyncCallback<T> {
|
||||||
|
(err: string, data: T): boolean;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface AsyncSuccess<T> {
|
||||||
|
(data: T);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface DataCallBack<T> {
|
||||||
|
callback(data: T);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {GlideData} from "../../glide/glidedata.ets"
|
||||||
|
|
||||||
|
export class AllCacheInfo {
|
||||||
|
memoryCacheInfo: {
|
||||||
|
key: string,
|
||||||
|
data: GlideData
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceCacheInfo: {
|
||||||
|
path: string,
|
||||||
|
key: string
|
||||||
|
}
|
||||||
|
|
||||||
|
dataCacheInfo: {
|
||||||
|
path: string,
|
||||||
|
key: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllCacheInfoCallback {
|
||||||
|
(cacheInfo: AllCacheInfo);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface IParseImage {
|
||||||
|
parseImage(imageinfo:ArrayBuffer, onCompleteFunction, onErrorFunction);
|
||||||
|
parseImageThumbnail(scale:number, imageinfo:ArrayBuffer, onCompleteFunction, onErrorFunction);
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {IDataFetch} from "../networkmanage/IDataFetch.ets"
|
||||||
|
import {RequestOption} from "../RequestOption.ets"
|
||||||
|
import {Md5} from "../../cache/Md5.ets"
|
||||||
|
import{FileUtils} from "../../cache/FileUtils.ets"
|
||||||
|
|
||||||
|
import httpRequest from '@ohos.request';
|
||||||
|
|
||||||
|
export class DownloadClient implements IDataFetch {
|
||||||
|
loadData(request: RequestOption, onCompleteFunction, onErrorFunction) {
|
||||||
|
|
||||||
|
let requestUrl = request.loadSrc as string;
|
||||||
|
if (requestUrl.startsWith("http") || requestUrl.startsWith("https")) {
|
||||||
|
let filename = Md5.hashStr(request.generateDataKey);
|
||||||
|
let allpath = request.networkCacheFolder + "/" + filename + ".img";
|
||||||
|
var downloadConfig = {
|
||||||
|
url: (request.loadSrc as string),
|
||||||
|
filePath: allpath
|
||||||
|
};
|
||||||
|
httpRequest.download(downloadConfig)
|
||||||
|
.then((downloadTask) => {
|
||||||
|
downloadTask.query((err, data) => {
|
||||||
|
if (err) {
|
||||||
|
onErrorFunction(err)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
downloadTask.on('progress', (uploadedSize, totalSize)=>{
|
||||||
|
let percent = Math.round(((uploadedSize*1.0)/(totalSize*1.0))*100)+"%"
|
||||||
|
if(request.progressFunc) {
|
||||||
|
request.progressFunc(percent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
downloadTask.on('complete', () => {
|
||||||
|
let downloadPath = request.getCachesPath() + "/" + allpath;
|
||||||
|
request.downloadFilePath = downloadPath;
|
||||||
|
let arraybuffer = FileUtils.getInstance()
|
||||||
|
.readFilePic(downloadPath)
|
||||||
|
onCompleteFunction(arraybuffer);
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.deleteFile(downloadPath);
|
||||||
|
})
|
||||||
|
downloadTask.on('fail', (err) => {
|
||||||
|
onErrorFunction("DownloadClient Download task fail. err =" + err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
onErrorFunction(err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
onErrorFunction("DownloadClient 暂不支持除http之外的uri加载")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {RequestOption} from "../RequestOption.ets"
|
||||||
|
|
||||||
|
// 网络接口
|
||||||
|
export interface IDataFetch {
|
||||||
|
loadData(request: RequestOption, onCompleteFunction, onErrorFunction);
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {IDataFetch} from "../networkmanage/IDataFetch.ets"
|
||||||
|
import {RequestOption} from "../RequestOption.ets"
|
||||||
|
import {Md5} from "../../cache/Md5.ets"
|
||||||
|
import {FileUtils} from "../../cache/FileUtils.ets"
|
||||||
|
import {ParseResClient} from "../../glide/resourcemanage/ParseResClient"
|
||||||
|
import resourceManager from '@ohos.resourceManager';
|
||||||
|
|
||||||
|
export class SimulatedDownloadClient implements IDataFetch {
|
||||||
|
loadData(request: RequestOption, onCompleteFunction, onErrorFunction) {
|
||||||
|
console.log("SimulatedDownloadClient loadData");
|
||||||
|
let requestUrl = request.loadSrc as string;
|
||||||
|
let resource;
|
||||||
|
//jpg
|
||||||
|
if('https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB' == requestUrl){
|
||||||
|
console.log("SimulatedDownloadClient jpg");
|
||||||
|
resource = $r('app.media.jpgNet')
|
||||||
|
}
|
||||||
|
//png
|
||||||
|
else if('https://img-blog.csdnimg.cn/20191215043500229.png' == requestUrl){
|
||||||
|
console.log("SimulatedDownloadClient png");
|
||||||
|
resource = $r('app.media.pngNet')
|
||||||
|
}
|
||||||
|
//bmp
|
||||||
|
else if('https://img-blog.csdn.net/20140514114029140' == requestUrl){
|
||||||
|
console.log("SimulatedDownloadClient bmp");
|
||||||
|
resource = $r('app.media.bmpNet')
|
||||||
|
}
|
||||||
|
//webp
|
||||||
|
else if('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp' == requestUrl){
|
||||||
|
console.log("SimulatedDownloadClient webp");
|
||||||
|
resource = $r('app.media.webpNet')
|
||||||
|
}
|
||||||
|
//svg
|
||||||
|
else if('http://design-svc.fat.lunz.cn/StaticFiles/BP9999999772/BV9999999422/SA9999998420/30df266a-485e-411e-b178-b9fb1d8e0748.svg' == requestUrl){
|
||||||
|
console.log("SimulatedDownloadClient svg");
|
||||||
|
resource = $r('app.media.svgNet')
|
||||||
|
}
|
||||||
|
//gif
|
||||||
|
else if('https://pic.ibaotu.com/gif/18/17/16/51u888piCtqj.gif!fwpaa70/fw/700'== requestUrl){
|
||||||
|
console.log("SimulatedDownloadClient gif");
|
||||||
|
resource = $r('app.media.gifNet')
|
||||||
|
}else{
|
||||||
|
new Error("SimulatedDownloadClient not support otherUrl")
|
||||||
|
}
|
||||||
|
|
||||||
|
let resClient = new ParseResClient();
|
||||||
|
resClient.loadResource(resource,(arraybuffer)=>{
|
||||||
|
console.log("SimulatedDownloadClient loadResource callback! ok")
|
||||||
|
if(request.progressFunc) {
|
||||||
|
request.progressFunc("100%")
|
||||||
|
}
|
||||||
|
onCompleteFunction(arraybuffer)
|
||||||
|
},onErrorFunction)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import {Closeable} from "/glide/pngj/io/Closeable.ets"
|
||||||
|
import {ImageInfo} from "/glide/pngj/entry/ImageInfo.ets"
|
||||||
|
|
||||||
|
export class PngReader implements Closeable {
|
||||||
|
private static LOG_TAG: string= "PngReader";
|
||||||
|
private static MAX_TOTAL_BYTES_READ_DEFAULT: number= 901001001;
|
||||||
|
private static MAX_BYTES_METADATA_DEFAULT: number= 5024024;
|
||||||
|
private static MAX_CHUNK_SIZE_SKIP: number= 2024024;
|
||||||
|
public imgInfo: ImageInfo;
|
||||||
|
public interlaced: boolean;
|
||||||
|
|
||||||
|
constructor(shouldCloseStream: boolean) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
import {UPNG} from '../pngj/UPNG.js';
|
||||||
|
import image from '@ohos.multimedia.image';
|
||||||
|
import resourceManager from '@ohos.resourceManager';
|
||||||
|
import featureability from '@ohos.ability.featureAbility'
|
||||||
|
|
||||||
|
export class Pngj {
|
||||||
|
readPngImageInfo(arraybuffer: ArrayBuffer, callback) {
|
||||||
|
let imageSource = image.createImageSource(arraybuffer);
|
||||||
|
imageSource.getImageInfo((err, value) => {
|
||||||
|
if (err) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param pngBuffer ArrayBuffer containing the PNG file
|
||||||
|
* @param callback
|
||||||
|
* returns an image object with following properties:
|
||||||
|
* width: the width of the image
|
||||||
|
* height: the height of the image
|
||||||
|
* depth: number of bits per channel
|
||||||
|
* ctype: color type of the file (Truecolor, Grayscale, Palette ...)
|
||||||
|
* frames: additional info about frames (frame delays etc.)
|
||||||
|
* tabs: additional chunks of the PNG file
|
||||||
|
* data: pixel data of the image
|
||||||
|
*/
|
||||||
|
readPngImage(pngBuffer: ArrayBuffer, callback) {
|
||||||
|
var png = UPNG.decode(pngBuffer);
|
||||||
|
callback(png)
|
||||||
|
}
|
||||||
|
|
||||||
|
writePngWithString(addInfo:string, pngBuffer: ArrayBuffer,callback) {
|
||||||
|
var pngDecode = UPNG.decode(pngBuffer);
|
||||||
|
var newPng = UPNG.encodeWithString(addInfo, UPNG.toRGBA8(pngDecode), pngDecode.width, pngDecode.height, 0)
|
||||||
|
callback(newPng);
|
||||||
|
}
|
||||||
|
|
||||||
|
writePng(pngBuffer: ArrayBuffer,callback) {
|
||||||
|
var pngDecode = UPNG.decode(pngBuffer);
|
||||||
|
var newPng = UPNG.encode(UPNG.toRGBA8(pngDecode), pngDecode.width, pngDecode.height, 0)
|
||||||
|
callback(newPng);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export class PngjException extends Error {
|
||||||
|
constructor(s: string) {
|
||||||
|
super(s)
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,166 @@
|
||||||
|
import {PngjException} from "../PngjException.ets"
|
||||||
|
|
||||||
|
export class ImageInfo {
|
||||||
|
private static MAX_COLS_ROW: number= 16777216;
|
||||||
|
private cols: number;
|
||||||
|
private rows: number;
|
||||||
|
private bitDepth: number;
|
||||||
|
private channels: number;
|
||||||
|
private alpha: boolean;
|
||||||
|
private greyscale: boolean;
|
||||||
|
private indexed: boolean;
|
||||||
|
private packed: boolean;
|
||||||
|
private bitspPixel: number;
|
||||||
|
private bytesPixel: number;
|
||||||
|
private bytesPerRow: number;
|
||||||
|
private samplesPerRow: number;
|
||||||
|
private samplesPerRowPacked: number ;
|
||||||
|
private totalPixels: number= -1;
|
||||||
|
private totalRawBytes: number= -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full constructor
|
||||||
|
*
|
||||||
|
* @param cols
|
||||||
|
* Width in pixels
|
||||||
|
* @param rows
|
||||||
|
* Height in pixels
|
||||||
|
* @param bitdepth
|
||||||
|
* Bits per sample, in the buffer : 8-16 for RGB true color and
|
||||||
|
* greyscale
|
||||||
|
* @param alpha
|
||||||
|
* Flag: has an alpha channel (RGBA or GA)
|
||||||
|
* @param grayscale
|
||||||
|
* Flag: is gray scale (any bitdepth, with or without alpha)
|
||||||
|
* @param indexed
|
||||||
|
* Flag: has palette
|
||||||
|
*/
|
||||||
|
constructor(cols: number, rows: number, bitdepth: number
|
||||||
|
, alpha: boolean, grayscale: boolean, indexed: boolean) {
|
||||||
|
this.cols = cols;
|
||||||
|
this.rows = rows;
|
||||||
|
this.alpha = alpha;
|
||||||
|
this.indexed = indexed;
|
||||||
|
this.greyscale = grayscale;
|
||||||
|
|
||||||
|
if (grayscale && indexed) {
|
||||||
|
throw new PngjException("palette and greyscale are mutually exclusive");
|
||||||
|
}
|
||||||
|
this.channels = (grayscale || indexed) ? (alpha ? 2 : 1) : (alpha ? 4 : 3);
|
||||||
|
this.bitDepth = bitdepth;
|
||||||
|
this.packed = bitdepth < 8;
|
||||||
|
this.bitspPixel = (this.channels * this.bitDepth);
|
||||||
|
this.bytesPixel = (this.bitspPixel + 7) / 8;
|
||||||
|
this.bytesPerRow = (this.bitspPixel * cols + 7) / 8;
|
||||||
|
this.samplesPerRow = this.channels * this.cols;
|
||||||
|
this.samplesPerRowPacked = this.packed ? this.bytesPerRow : this.samplesPerRow;
|
||||||
|
|
||||||
|
switch (this.bitDepth) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
if (!(this.indexed || this.greyscale))
|
||||||
|
throw new PngjException("only indexed or grayscale can have bitdepth=" + this.bitDepth);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
if (this.indexed) {
|
||||||
|
throw new PngjException("indexed can't have bitdepth=" + this.bitDepth);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new PngjException("invalid bitdepth=" + this.bitDepth);
|
||||||
|
}
|
||||||
|
if (cols < 1 || cols > ImageInfo.MAX_COLS_ROW) {
|
||||||
|
throw new PngjException("invalid cols=" + cols + " ???");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows < 1 || rows > ImageInfo.MAX_COLS_ROW) {
|
||||||
|
throw new PngjException("invalid rows=" + rows + " ???");
|
||||||
|
}
|
||||||
|
if (this.samplesPerRow < 1) {
|
||||||
|
throw new PngjException("invalid image parameters (overflow?)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a copy with different size
|
||||||
|
*
|
||||||
|
* @param cols
|
||||||
|
* if non-positive, the original is used
|
||||||
|
* @param rows
|
||||||
|
* if non-positive, the original is used
|
||||||
|
* @return a new copy with the specified size and same properties
|
||||||
|
*/
|
||||||
|
public withSize(cols: number, rows: number): ImageInfo {
|
||||||
|
return new ImageInfo(cols > 0 ? cols : this.cols, rows > 0 ? rows : this.rows, this.bitDepth, this.alpha,
|
||||||
|
this.greyscale, this.indexed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTotalPixels(): number {
|
||||||
|
if (this.totalPixels < 0)
|
||||||
|
this.totalPixels = this.cols * this.rows;
|
||||||
|
return this.totalPixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTotalRawBytes(): number {
|
||||||
|
if (this.totalRawBytes < 0)
|
||||||
|
this.totalRawBytes = (this.bytesPerRow + 1) * this.rows;
|
||||||
|
return this.totalRawBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toString(): string{
|
||||||
|
return "ImageInfo [cols=" + this.cols + ", rows=" + this.rows + ", bitDepth="
|
||||||
|
+ this.bitDepth + ", channels=" + this.channels
|
||||||
|
+ ", alpha=" + this.alpha + ", greyscale="
|
||||||
|
+ this.greyscale + ", indexed=" + this.indexed + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public toStringBrief(): string{
|
||||||
|
return this.cols + "x" + this.rows + (this.bitDepth != 8 ? ("d" + this.bitDepth) : "") + (this.alpha ? "a" : "")
|
||||||
|
+ (this.indexed ? "p" : "") + (this.greyscale ? "g" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public toStringDetail(): string{
|
||||||
|
return "ImageInfo [cols=" + this.cols + ", rows=" + this.rows + ", bitDepth="
|
||||||
|
+ this.bitDepth + ", channels=" + this.channels + ", bitspPixel=" + this.bitspPixel
|
||||||
|
+ ", bytesPixel=" + this.bytesPixel + ", bytesPerRow=" + this.bytesPerRow
|
||||||
|
+ ", samplesPerRow=" + this.samplesPerRow + ", samplesPerRowP=" + this.samplesPerRowPacked
|
||||||
|
+ ", alpha=" + this.alpha + ", greyscale=" + this.greyscale + ", indexed=" + this.indexed
|
||||||
|
+ ", packed=" + this.packed + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public hashCode(): number {
|
||||||
|
const prime: number = 31;
|
||||||
|
let result: number = 1;
|
||||||
|
result = prime * result + (this.alpha ? 1231 : 1237);
|
||||||
|
result = prime * result + this.bitDepth;
|
||||||
|
result = prime * result + this.cols;
|
||||||
|
result = prime * result + (this.greyscale ? 1231 : 1237);
|
||||||
|
result = prime * result + (this.indexed ? 1231 : 1237);
|
||||||
|
result = prime * result + this.rows;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public equals(obj: ImageInfo): boolean {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
var other = obj;
|
||||||
|
if (this.alpha != other.alpha)
|
||||||
|
return false;
|
||||||
|
if (this.bitDepth != other.bitDepth)
|
||||||
|
return false;
|
||||||
|
if (this.cols != other.cols)
|
||||||
|
return false;
|
||||||
|
if (this.greyscale != other.greyscale)
|
||||||
|
return false;
|
||||||
|
if (this.indexed != other.indexed)
|
||||||
|
return false;
|
||||||
|
if (this.rows != other.rows)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface IBytesConsumer {
|
||||||
|
isDone(): boolean;
|
||||||
|
|
||||||
|
consume(buf: ArrayBuffer, offset: number, len: number): number;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface Closeable {
|
||||||
|
close(): void;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export class Sandbox {
|
||||||
|
|
||||||
|
|
||||||
|
public static convert(origFileName: string, destFileName: string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {ICache} from "../requestmanage/ICache.ets"
|
||||||
|
import {DiskLruCache} from "../../cache/DiskLruCache.ets"
|
||||||
|
|
||||||
|
export class DiskCacheProxy implements ICache<string, ArrayBuffer> {
|
||||||
|
private mDiskLruCache: DiskLruCache;
|
||||||
|
|
||||||
|
constructor(diskLruCache: DiskLruCache) {
|
||||||
|
this.mDiskLruCache = diskLruCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存类型
|
||||||
|
getName(): string{
|
||||||
|
return "Level2DiskCache";
|
||||||
|
}
|
||||||
|
|
||||||
|
getCachePath():string{
|
||||||
|
let folderPath = this.mDiskLruCache.dirPath
|
||||||
|
if (folderPath.endsWith('/')) {
|
||||||
|
return folderPath;
|
||||||
|
} else {
|
||||||
|
return folderPath + '/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue(key: string): ArrayBuffer{
|
||||||
|
return this.mDiskLruCache.getCacheDataByKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
putValue(key: string, value: ArrayBuffer) {
|
||||||
|
this.mDiskLruCache.putCacheData(key, value, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeValue(key: string): ArrayBuffer{
|
||||||
|
// Disk暂无实现
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.mDiskLruCache.cleanCacheData();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ICache<K, V> {
|
||||||
|
|
||||||
|
// 缓存类型
|
||||||
|
getName(): string
|
||||||
|
|
||||||
|
getValue(key: K): V;
|
||||||
|
|
||||||
|
putValue(key: K, value: V);
|
||||||
|
|
||||||
|
removeValue(key: K): V;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {ICache} from "../requestmanage/ICache.ets"
|
||||||
|
import {LruCache} from "../../cache/LruCache"
|
||||||
|
|
||||||
|
export class MemoryCacheProxy <K, V> implements ICache<K, V> {
|
||||||
|
private mLruCache: LruCache<K, V>;
|
||||||
|
|
||||||
|
constructor(lruCache: LruCache<K, V>) {
|
||||||
|
this.mLruCache = lruCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存类型
|
||||||
|
getName() {
|
||||||
|
return "Level1MemoryCache"
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue(key: K): V{
|
||||||
|
console.log("Level1MemoryCache getValue come in!");
|
||||||
|
return this.mLruCache.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
putValue(key: K, value: V) {
|
||||||
|
this.mLruCache.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeValue(key: K): V{
|
||||||
|
return this.mLruCache.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.mLruCache.evicAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 外界调用
|
||||||
|
loadMemoryCache(key: K, isMemoryCacheable: boolean): V{
|
||||||
|
// 是否开启内存缓存
|
||||||
|
if (!isMemoryCacheable) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let cached = this.getValue(key)
|
||||||
|
if (cached != null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,582 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {DiskLruCache} from "../../cache/DiskLruCache.ets"
|
||||||
|
import {LruCache} from "../../cache/LruCache"
|
||||||
|
import {FileUtils} from "../../cache/FileUtils.ets"
|
||||||
|
import {Md5} from "../../cache/Md5.ets"
|
||||||
|
import{MemoryCacheProxy} from "../requestmanage/MemoryCacheProxy.ets"
|
||||||
|
import{DiskCacheProxy} from "../requestmanage/DiskCacheProxy.ets"
|
||||||
|
import{FileTypeUtil} from "../utils/FileTypeUtil.ets"
|
||||||
|
import{IDataFetch} from "../../glide/networkmanage/IDataFetch.ets"
|
||||||
|
import{IResourceFetch} from "../../glide/resourcemanage/IResourceFetch.ets"
|
||||||
|
import{GlideData} from "../GlideData.ets"
|
||||||
|
import {AllCacheInfo, IAllCacheInfoCallback} from "../../glide/interface/iallcacheinfocallback.ets"
|
||||||
|
import{ParseImageUtil} from '../utils/ParseImageUtil'
|
||||||
|
import{IParseImage} from '../interface/IParseImage.ets'
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export interface AsyncString {
|
||||||
|
(data: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Stage {
|
||||||
|
|
||||||
|
INITIALIZE,
|
||||||
|
|
||||||
|
RESOURCE_CACHE,
|
||||||
|
|
||||||
|
DATA_CACHE,
|
||||||
|
|
||||||
|
SOURCE,
|
||||||
|
|
||||||
|
ENCODE,
|
||||||
|
|
||||||
|
FINISHED,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export enum RunReason {
|
||||||
|
|
||||||
|
INITIALIZE,
|
||||||
|
|
||||||
|
SWITCH_TO_SOURCE_SERVICE,
|
||||||
|
|
||||||
|
DECODE_DATA,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RequestManager {
|
||||||
|
private TAG: string = "RequestManager";
|
||||||
|
private options: RequestOption;
|
||||||
|
private mMemoryCacheProxy: MemoryCacheProxy<string, any>;
|
||||||
|
private mDiskCacheProxy: DiskCacheProxy;
|
||||||
|
private mIDataFetch: IDataFetch;
|
||||||
|
private mIResourceFetch: IResourceFetch;
|
||||||
|
private mParseImageUtil: IParseImage;
|
||||||
|
|
||||||
|
constructor(option: RequestOption, memoryCache1: LruCache<string, any>, diskMemoryCache1: DiskLruCache, dataFetch: IDataFetch, resourceFetch: IResourceFetch) {
|
||||||
|
this.options = option;
|
||||||
|
|
||||||
|
// 缓存部分
|
||||||
|
this.mMemoryCacheProxy = new MemoryCacheProxy(memoryCache1);
|
||||||
|
this.mDiskCacheProxy = new DiskCacheProxy(diskMemoryCache1);
|
||||||
|
|
||||||
|
// 网络下载能力
|
||||||
|
this.mIDataFetch = dataFetch;
|
||||||
|
|
||||||
|
// 本地数据解析能力
|
||||||
|
this.mIResourceFetch = resourceFetch;
|
||||||
|
|
||||||
|
// 解析image能力
|
||||||
|
this.mParseImageUtil = new ParseImageUtil();
|
||||||
|
}
|
||||||
|
|
||||||
|
static execute(option: RequestOption, memoryCache1: LruCache<string, any>, diskMemoryCache1: DiskLruCache, dataFetch: IDataFetch, resourceFetch: IResourceFetch) {
|
||||||
|
console.log("RequestManager execute")
|
||||||
|
let manager = new RequestManager(option, memoryCache1, diskMemoryCache1, dataFetch, resourceFetch);
|
||||||
|
return new Promise<PixelMap>(manager.process.bind(manager))
|
||||||
|
.then(option.loadComplete.bind(option))
|
||||||
|
.then(manager.loadCompleteAfter.bind(manager))
|
||||||
|
.catch(option.loadError.bind(option));
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCompleteAfter() {
|
||||||
|
try { // 内部消化问题
|
||||||
|
console.log("loadCompleteAfter!")
|
||||||
|
if (this.options.allCacheInfoCallback) {
|
||||||
|
console.log("RequestOption =" + JSON.stringify(this.options));
|
||||||
|
|
||||||
|
// 内存缓存
|
||||||
|
let allCacheInfo = new AllCacheInfo();
|
||||||
|
let memoryCache = this.mMemoryCacheProxy.getValue(this.options.generateCacheKey);
|
||||||
|
allCacheInfo.memoryCacheInfo = {
|
||||||
|
key: this.options.generateCacheKey,
|
||||||
|
data: memoryCache
|
||||||
|
}
|
||||||
|
|
||||||
|
// 变换后缓存
|
||||||
|
allCacheInfo.resourceCacheInfo = {
|
||||||
|
key: Md5.hashStr(this.options.generateResourceKey),
|
||||||
|
path: (this.mDiskCacheProxy.getCachePath() + Md5.hashStr(this.options.generateResourceKey))
|
||||||
|
};
|
||||||
|
|
||||||
|
// 原图缓存
|
||||||
|
allCacheInfo.dataCacheInfo = {
|
||||||
|
key: Md5.hashStr(this.options.generateDataKey),
|
||||||
|
path: this.mDiskCacheProxy.getCachePath() + Md5.hashStr(this.options.generateDataKey)
|
||||||
|
}
|
||||||
|
this.options.allCacheInfoCallback(allCacheInfo)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("after err =" + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// DecodeJob work
|
||||||
|
private mStage: Stage = Stage.INITIALIZE;
|
||||||
|
private mRunReason: RunReason = RunReason.INITIALIZE;
|
||||||
|
|
||||||
|
process(onComplete, onError) {
|
||||||
|
console.log("RequestManager process !");
|
||||||
|
this.loadLeve1MemoryCache(onComplete, onError)
|
||||||
|
}
|
||||||
|
|
||||||
|
private runWrapped(request: RequestOption, runReason: RunReason, onComplete, onError) {
|
||||||
|
console.log("RequestManager runWrapped")
|
||||||
|
if (runReason == RunReason.INITIALIZE) {
|
||||||
|
this.mStage = this.getNextStage(request, this.mStage);
|
||||||
|
this.searchLoadFrom(this.options, this.mStage, onComplete, onError);
|
||||||
|
} else {
|
||||||
|
throw new Error("Unrecognized run reason: " + runReason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getNextStage(request: RequestOption, current: Stage): Stage{
|
||||||
|
if (current == Stage.INITIALIZE) {
|
||||||
|
return request.strategy.decodeCachedResource()
|
||||||
|
? Stage.RESOURCE_CACHE
|
||||||
|
: this.getNextStage(request, Stage.RESOURCE_CACHE);
|
||||||
|
} else if (current == Stage.RESOURCE_CACHE) {
|
||||||
|
return request.strategy.decodeCachedData()
|
||||||
|
? Stage.DATA_CACHE
|
||||||
|
: this.getNextStage(request, Stage.DATA_CACHE);
|
||||||
|
} else if (current == Stage.DATA_CACHE) {
|
||||||
|
return request.onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
|
||||||
|
} else if (current == Stage.SOURCE) {
|
||||||
|
return Stage.FINISHED;
|
||||||
|
} else if (current == Stage.FINISHED) {
|
||||||
|
return Stage.FINISHED;
|
||||||
|
} else {
|
||||||
|
throw new Error("Unrecognized stage: " + current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//究竟从哪里加载数据
|
||||||
|
private searchLoadFrom(request: RequestOption, current: Stage, onComplete, onError) {
|
||||||
|
console.log("RequestManager searchLoadFrom")
|
||||||
|
if (current == Stage.RESOURCE_CACHE) {
|
||||||
|
this.loadDiskFromTransform(request, onComplete, onError);
|
||||||
|
} else if (current == Stage.DATA_CACHE) {
|
||||||
|
this.loadDiskFromSource(request, onComplete, onError);
|
||||||
|
} else if (current == Stage.SOURCE) {
|
||||||
|
this.parseSource(request, onComplete, onError)
|
||||||
|
} else if (current == Stage.FINISHED) {
|
||||||
|
onError("在仅从缓存获取数据中,未获取到数据!")
|
||||||
|
} else {
|
||||||
|
throw new Error("Unrecognized stage: " + current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载网络资源
|
||||||
|
private loadSourceFromNetwork(request: RequestOption, onComplete, onError) {
|
||||||
|
let success = (arraybuffer) => {
|
||||||
|
this.downloadSuccess(arraybuffer, onComplete, onError)
|
||||||
|
}
|
||||||
|
this.mIDataFetch.loadData(request, success, onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载本地资源
|
||||||
|
private loadSourceFormNative(request: RequestOption, onComplete, onError) {
|
||||||
|
console.log("RequestManager loadSourceFormNative")
|
||||||
|
// 本地解析后进行一级缓存
|
||||||
|
let success = (arrayBuffer) => {
|
||||||
|
// 使用媒体子系统 ImageSource解析文件 获取PixelMap
|
||||||
|
let fileTypeUtil = new FileTypeUtil();
|
||||||
|
let typeValue = fileTypeUtil.getFileType(arrayBuffer)
|
||||||
|
console.log("RequstManager - 文件类型为= " + typeValue)
|
||||||
|
if ((GlideData.GIF == typeValue && !request.dontAnimateFlag) || GlideData.SVG == typeValue) {
|
||||||
|
// 将图片资源 转换为文件地址
|
||||||
|
let folderPath = this.options.getFilesPath() + "/" + this.options._svgAndGifFolder;
|
||||||
|
let filePath = this.options.getFilesPath() + "/" + this.options._svgAndGifFolder + "/"
|
||||||
|
+ Md5.hashStr(this.options.generateDataKey) + "." + typeValue;
|
||||||
|
let filename = Md5.hashStr(this.options.generateDataKey) + "." + typeValue;
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
// 存文件至svg目录,并且记录文件名
|
||||||
|
resolve("svg gif 文件开始本地保存!");
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
// 创建文件
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.createFileProcess(folderPath, filePath, arrayBuffer);
|
||||||
|
// 写入记录
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.writeData(this.options.getFilesPath() +
|
||||||
|
"/" + this.options._svgAndGifFolder + "/" + this.options._svgAndGifCommitFile, filename + "\n");
|
||||||
|
console.log("svg gif 本地保存成功 输出!");
|
||||||
|
let glidedata = this.createGlideData(GlideData.STRING, filePath, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
onError(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (request.transformtions[0]) {
|
||||||
|
request.transformtions[0].transform(arrayBuffer, request, (error, pixelMap: PixelMap) => {
|
||||||
|
// 输出给Image
|
||||||
|
if (pixelMap) {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, pixelMap, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(request.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
} else {
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(request.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImage(arrayBuffer, success, onError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.mIResourceFetch.loadResource(request.loadSrc as Resource, success, onError);
|
||||||
|
}
|
||||||
|
// 加载磁盘缓存 原图
|
||||||
|
private loadDiskFromSource(request: RequestOption, onComplete, onError) {
|
||||||
|
console.log("RequestManager loadDiskFromSource")
|
||||||
|
let cached = this.mDiskCacheProxy.getValue(request.generateDataKey)
|
||||||
|
if (cached != null) {
|
||||||
|
this.parseDiskFile2PixelMap(request, cached, onComplete, onError)
|
||||||
|
} else {
|
||||||
|
this.mStage = Stage.SOURCE;
|
||||||
|
this.searchLoadFrom(this.options, this.mStage, onComplete, onError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载磁盘缓存 变换后图片
|
||||||
|
private loadDiskFromTransform(request: RequestOption, onComplete, onError) {
|
||||||
|
console.log("RequestManager loadDiskFromTransform")
|
||||||
|
let cached = this.mDiskCacheProxy.getValue(request.generateResourceKey)
|
||||||
|
if (cached != null) {
|
||||||
|
this.parseDiskTransformFile2PixelMap(request, cached, onComplete, onError)
|
||||||
|
} else {
|
||||||
|
this.mStage = Stage.DATA_CACHE;
|
||||||
|
this.searchLoadFrom(this.options, this.mStage, onComplete, onError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseSource(request: RequestOption, onComplete, onError) {
|
||||||
|
console.log("RequestManager parseSource")
|
||||||
|
if (request.loadSrc instanceof image.PixelMap) {
|
||||||
|
// PixelMap 外层捕获效率更高,不会进入这里
|
||||||
|
} else if (typeof request.loadSrc == 'string') {
|
||||||
|
this.loadSourceFromNetwork(request, onComplete, onError);
|
||||||
|
} else {
|
||||||
|
let res = request.loadSrc as Resource;
|
||||||
|
if (typeof res.id != 'undefined' && typeof res.id != 'undefined') {
|
||||||
|
this.loadSourceFormNative(request, onComplete, onError)
|
||||||
|
} else {
|
||||||
|
console.log("输入参数有问题!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadLeve1MemoryCache(onComplete, onError) {
|
||||||
|
console.log("RequestManager loadLeve1MemoryCache")
|
||||||
|
// 一级缓存 内存获取
|
||||||
|
let cache = this.mMemoryCacheProxy.loadMemoryCache(this.options.generateCacheKey, this.options.isCacheable);
|
||||||
|
if (cache == null || typeof cache == 'undefined') {
|
||||||
|
// 处理磁盘加载 网络加载
|
||||||
|
this.runWrapped(this.options, this.mRunReason, onComplete, onError)
|
||||||
|
} else {
|
||||||
|
onComplete(cache);
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析磁盘文件变成PixeMap
|
||||||
|
private parseDiskFile2PixelMap(request: RequestOption, source: ArrayBuffer, onComplete, onError) {
|
||||||
|
// 步骤一:文件转为pixelMap 然后变换 给Image组件
|
||||||
|
let fileTypeUtil = new FileTypeUtil();
|
||||||
|
let typeValue = fileTypeUtil.getFileType(source);
|
||||||
|
if (((GlideData.GIF == typeValue && !request.dontAnimateFlag) || GlideData.SVG == typeValue)) {
|
||||||
|
// 将图片资源 转换为文件地址
|
||||||
|
let folderPath = this.options.getFilesPath() + "/" + this.options._svgAndGifFolder;
|
||||||
|
let filePath = this.options.getFilesPath() + "/" + this.options._svgAndGifFolder + "/"
|
||||||
|
+ Md5.hashStr(this.options.generateDataKey) + "." + typeValue;
|
||||||
|
let filename = Md5.hashStr(this.options.generateDataKey) + "." + typeValue;
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
// 存文件至svg目录,并且记录文件名
|
||||||
|
resolve("svg gif 文件开始本地保存!");
|
||||||
|
}).then((res) => {
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.createFileProcess(folderPath, filePath, source);
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.writeData(this.options.getFilesPath() +
|
||||||
|
"/" + this.options._svgAndGifFolder + "/" + this.options._svgAndGifCommitFile, filename + "\n");
|
||||||
|
let glidedata = this.createGlideData(GlideData.STRING, filePath, typeValue)
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
onError(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (this.options.transformtions[0]) {
|
||||||
|
if (this.options.thumbSizeMultiplier) {
|
||||||
|
let thumbOption = new RequestOption();
|
||||||
|
thumbOption.setImageViewSize({
|
||||||
|
width: Math.round(this.options.thumbSizeMultiplier * this.options.size.width),
|
||||||
|
height: Math.round(this.options.thumbSizeMultiplier * this.options.size.height)
|
||||||
|
})
|
||||||
|
let thumbCallback = this.options.thumbholderOnComplete.bind(this.options);
|
||||||
|
let thumbError = this.options.thumbholderOnError.bind(this.options);
|
||||||
|
this.options.transformtions[0].transform(source, thumbOption, (error, pixelMap: PixelMap) => {
|
||||||
|
if (pixelMap) {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, pixelMap, typeValue);
|
||||||
|
thumbCallback(glidedata);
|
||||||
|
} else {
|
||||||
|
thumbError(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.options.transformtions[0].transform(source, request, (error, pixelMap: PixelMap) => {
|
||||||
|
if (pixelMap) {
|
||||||
|
// 保存一份变换后的图片PixelMap到MemoryCache
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, pixelMap, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
} else {
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},this.options.thumbDelayTime);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.options.transformtions[0].transform(source, request, (error, pixelMap: PixelMap) => {
|
||||||
|
if (pixelMap) {
|
||||||
|
// 保存一份变换后的图片PixelMap到MemoryCache
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, pixelMap, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
} else {
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// thumbnail 缩略图部分
|
||||||
|
if (request.thumbSizeMultiplier) {
|
||||||
|
let thumbCallback = this.options.thumbholderOnComplete.bind(this.options);
|
||||||
|
let thumbError = this.options.thumbholderOnError.bind(this.options);
|
||||||
|
let thumbSuccess = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, typeValue);
|
||||||
|
thumbCallback(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImageThumbnail(request.thumbSizeMultiplier, source, thumbSuccess, thumbError);
|
||||||
|
setTimeout(()=>{
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImage(source, success, onError)
|
||||||
|
},this.options.thumbDelayTime)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImage(source, success, onError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析磁盘变换后文件变成PixeMap
|
||||||
|
private parseDiskTransformFile2PixelMap(request: RequestOption, source: ArrayBuffer, onComplete, onError) {
|
||||||
|
let fileTypeUtil = new FileTypeUtil();
|
||||||
|
let typeValue = fileTypeUtil.getFileType(source);
|
||||||
|
// thumbnail 缩略图部分
|
||||||
|
if (request.thumbSizeMultiplier) {
|
||||||
|
let thumbCallback = this.options.thumbholderOnComplete.bind(this.options);
|
||||||
|
let thumbError = this.options.thumbholderOnError.bind(this.options);
|
||||||
|
let thumbSuccess = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, typeValue);
|
||||||
|
thumbCallback(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImageThumbnail(request.thumbSizeMultiplier, source, thumbSuccess, thumbError);
|
||||||
|
setTimeout(()=>{
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, typeValue);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImage(source, success, onError)
|
||||||
|
},this.options.thumbDelayTime)
|
||||||
|
}else{
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, typeValue)
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImage(source, success, onError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private downloadSuccess(source: ArrayBuffer, onComplete, onError) {
|
||||||
|
console.info('Download task completed.');
|
||||||
|
|
||||||
|
// 下载成功之后 去data/data/包名/唯一路径/文件名 读取数据
|
||||||
|
// 步骤一:文件转为pixelMap 然后变换 给Image组件
|
||||||
|
// 步骤二: 文件名保存一份全局
|
||||||
|
// 步骤三:查看文件是否支持 非支持类型直接返回
|
||||||
|
let fileTypeUtil = new FileTypeUtil();
|
||||||
|
let filetype = fileTypeUtil.getFileType(source);
|
||||||
|
if (!fileTypeUtil.isImage(source)) {
|
||||||
|
onError("暂不支持 下载文件类型!类型=" + filetype);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((GlideData.GIF == filetype && !this.options.dontAnimateFlag) || GlideData.SVG == filetype) {
|
||||||
|
// 将图片资源 转换为文件地址
|
||||||
|
let folderPath = this.options.getFilesPath() + "/" + this.options._svgAndGifFolder;
|
||||||
|
let filePath = this.options.getFilesPath() + "/" + this.options._svgAndGifFolder + "/"
|
||||||
|
+ Md5.hashStr(this.options.generateDataKey) + "." + filetype;
|
||||||
|
let filename = Md5.hashStr(this.options.generateDataKey) + "." + filetype;
|
||||||
|
// 1.文件保存 2.内存缓存 3.输出结果
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
// 存文件至svg目录,并且记录文件名
|
||||||
|
resolve("svg gif 文件开始本地保存!");
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.createFileProcess(folderPath, filePath, source);
|
||||||
|
FileUtils.getInstance()
|
||||||
|
.writeData(this.options.getFilesPath() +
|
||||||
|
"/" + this.options._svgAndGifFolder + "/" + this.options._svgAndGifCommitFile, filename + "\n");
|
||||||
|
let glidedata = this.createGlideData(GlideData.STRING, filePath, filetype);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
onComplete(glidedata);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
onError(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 保存二级磁盘缓存
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
resolve(source)
|
||||||
|
})
|
||||||
|
.then((arraybuffer: ArrayBuffer) => {
|
||||||
|
this.mDiskCacheProxy.putValue(this.options.generateDataKey, arraybuffer)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("err=" + err);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 进行变换
|
||||||
|
if (this.options.transformtions[0]) {
|
||||||
|
// thumbnail 缩略图部分
|
||||||
|
if (this.options.thumbSizeMultiplier) {
|
||||||
|
this.thumbnailProcess(source, filetype, onComplete, onError);
|
||||||
|
} else {
|
||||||
|
this.options.transformtions[0].transform(source, this.options, (error, pixelMap: PixelMap) => {
|
||||||
|
if (pixelMap) {
|
||||||
|
this.saveCacheAndDisk(pixelMap, filetype, onComplete, source);
|
||||||
|
} else {
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// thumbnail 缩略图部分
|
||||||
|
if (this.options.thumbSizeMultiplier) {
|
||||||
|
let thumbCallback = this.options.thumbholderOnComplete.bind(this.options);
|
||||||
|
let thumbError = this.options.thumbholderOnError.bind(this.options);
|
||||||
|
let thumbSuccess = (value: PixelMap) => {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, filetype);
|
||||||
|
thumbCallback(glidedata);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImageThumbnail(this.options.thumbSizeMultiplier, source, thumbSuccess, thumbError);
|
||||||
|
setTimeout(() => {
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
this.saveCacheAndDisk(value, filetype, onComplete, source);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImage(source, success, onError)
|
||||||
|
}, this.options.thumbDelayTime)
|
||||||
|
} else {
|
||||||
|
let success = (value: PixelMap) => {
|
||||||
|
this.saveCacheAndDisk(value, filetype, onComplete, source);
|
||||||
|
}
|
||||||
|
this.mParseImageUtil.parseImage(source, success, onError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
createGlideData(glideType:string, glideValue:PixelMap|string|Resource, glideSourceType:string):GlideData{
|
||||||
|
let glidedata = new GlideData();
|
||||||
|
glidedata.glideType = glideType;
|
||||||
|
glidedata.glideValue = glideValue;
|
||||||
|
glidedata.glideSourceType = glideSourceType;
|
||||||
|
return glidedata;
|
||||||
|
}
|
||||||
|
|
||||||
|
private saveCacheAndDisk(value: PixelMap, filetype:string, onComplete, source:ArrayBuffer){
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, value, filetype);
|
||||||
|
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, glidedata);
|
||||||
|
let save2DiskCache = (arraybuffer) => {
|
||||||
|
this.mDiskCacheProxy.putValue(this.options.generateDataKey, arraybuffer)
|
||||||
|
}
|
||||||
|
let runSave2Disk = (resolve, reject) => {
|
||||||
|
resolve(source);
|
||||||
|
}
|
||||||
|
let promise = new Promise(runSave2Disk);
|
||||||
|
promise.then(save2DiskCache);
|
||||||
|
onComplete(glidedata);
|
||||||
|
}
|
||||||
|
|
||||||
|
thumbnailProcess(source:ArrayBuffer, filetype:string, onComplete, onError){
|
||||||
|
let thumbOption = new RequestOption();
|
||||||
|
thumbOption.setImageViewSize({
|
||||||
|
width: Math.round(this.options.thumbSizeMultiplier * this.options.size.width),
|
||||||
|
height: Math.round(this.options.thumbSizeMultiplier * this.options.size.height)
|
||||||
|
})
|
||||||
|
let thumbCallback = this.options.thumbholderOnComplete.bind(this.options);
|
||||||
|
let thumbError = this.options.thumbholderOnError.bind(this.options);
|
||||||
|
this.options.transformtions[0].transform(source, thumbOption, (error, pixelMap: PixelMap) => {
|
||||||
|
if (pixelMap) {
|
||||||
|
let glidedata = this.createGlideData(GlideData.PIXELMAP, pixelMap, filetype);
|
||||||
|
thumbCallback(glidedata);
|
||||||
|
} else {
|
||||||
|
thumbError(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
this.options.transformtions[0].transform(source, this.options, (error, pixelMap: PixelMap) => {
|
||||||
|
if (pixelMap) {
|
||||||
|
this.saveCacheAndDisk(pixelMap, filetype, onComplete, source);
|
||||||
|
} else {
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, this.options.thumbDelayTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {RequestOption} from "../RequestOption.ets"
|
||||||
|
|
||||||
|
// 本地资源解析抽象接口
|
||||||
|
export interface IResourceFetch {
|
||||||
|
loadResource(res: Resource, onCompleteFunction, onErrorFunction);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {IResourceFetch} from '../resourcemanage/IResourceFetch.ets'
|
||||||
|
import {ResourceTypeEts} from '../../glide/constants/ResourceTypeEts.ets'
|
||||||
|
|
||||||
|
import resourceManager from '@ohos.resourceManager';
|
||||||
|
|
||||||
|
export class ParseResClient implements IResourceFetch {
|
||||||
|
loadResource(res: Resource, onCompleteFunction, onErrorFunction) {
|
||||||
|
let resId = res.id;
|
||||||
|
let resType = res.type;
|
||||||
|
if (resType == ResourceTypeEts.MEDIA) {
|
||||||
|
resourceManager.getResourceManager()
|
||||||
|
.then(result => {
|
||||||
|
result.getMedia(resId)
|
||||||
|
.then(data => {
|
||||||
|
let arrayBuffer = this.typedArrayToBuffer(data);
|
||||||
|
onCompleteFunction(arrayBuffer)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
onErrorFunction(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if (resType == ResourceTypeEts.RAWFILE) {
|
||||||
|
onErrorFunction('ParseResClient 本地资源是rawfile暂时无法解析出错')
|
||||||
|
} else {
|
||||||
|
onErrorFunction('ParseResClient 本地资源不是media也不是rawfile无法解析出错')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedArrayToBuffer(array: Uint8Array): ArrayBuffer {
|
||||||
|
return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {IResourceFetch} from '../resourcemanage/IResourceFetch.ets'
|
||||||
|
import {ResourceTypeEts} from '../../glide/constants/ResourceTypeEts.ets'
|
||||||
|
import {Base64} from '../../cache/Base64.ets'
|
||||||
|
|
||||||
|
import resourceManager from '@ohos.resourceManager';
|
||||||
|
|
||||||
|
export class ParseResClientBase64 implements IResourceFetch {
|
||||||
|
loadResource(res: Resource, onCompleteFunction, onErrorFunction) {
|
||||||
|
let resId = res.id;
|
||||||
|
let resType = res.type;
|
||||||
|
if (resType == ResourceTypeEts.MEDIA) {
|
||||||
|
resourceManager.getResourceManager()
|
||||||
|
.then(result => {
|
||||||
|
result.getMediaBase64(resId)
|
||||||
|
.then(data => {
|
||||||
|
let matchReg = ';base64,';
|
||||||
|
var firstIndex = data.indexOf(matchReg)
|
||||||
|
data = data.substring(firstIndex + matchReg.length, data.length)
|
||||||
|
let arrayBuffer = Base64.getInstance()
|
||||||
|
.decode(data);
|
||||||
|
onCompleteFunction(arrayBuffer)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
onErrorFunction(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if (resType == ResourceTypeEts.RAWFILE) {
|
||||||
|
onErrorFunction('ParseResClientBase64 本地资源是rawfile暂时无法解析出错')
|
||||||
|
} else {
|
||||||
|
onErrorFunction('ParseResClientBase64 本地资源不是media也不是rawfile无法解析出错')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface AsyncTransform<T> {
|
||||||
|
(err, data: T)
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
|
||||||
|
export interface BaseTransform<T> {
|
||||||
|
//实现类 返回作为key生成的一部分
|
||||||
|
getName(): string;
|
||||||
|
|
||||||
|
transform(value: ArrayBuffer, request: RequestOption, func: AsyncTransform<T>);
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
import {fastBlur} from "../utils/FastBlur"
|
||||||
|
|
||||||
|
|
||||||
|
export class BlurTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private _mRadius: number;
|
||||||
|
|
||||||
|
constructor(radius: number) {
|
||||||
|
this._mRadius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return "BlurTransformation _mRadius:" + this._mRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";BlurTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";BlurTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((data) => {
|
||||||
|
fastBlur.blur(data, this._mRadius, true, func);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||||
|
func(e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brightness value ranges from -1.0 to 1.0, with 0.0 as the normal level
|
||||||
|
*/
|
||||||
|
export class BrightnessFilterTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private _mBrightness: number= 0.0;
|
||||||
|
|
||||||
|
constructor(brightness: number) {
|
||||||
|
this._mBrightness = brightness;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return "BrightnessFilterTransformation:" + this._mBrightness;
|
||||||
|
}
|
||||||
|
|
||||||
|
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";GrayscaleTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";GrayscaleTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
|
||||||
|
let imageInfo = await imageSource.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("GrayscaleTransformation The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data = await imageSource.createPixelMap(options);
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
|
||||||
|
for (let w = 0;w <= targetWidth; w++) {
|
||||||
|
for (let h = 0;h <= targetHeight; h++) {
|
||||||
|
var buffer = new ArrayBuffer(5);
|
||||||
|
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
|
||||||
|
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var bytes = new Uint8Array(buffer);
|
||||||
|
var buffer1B = new ArrayBuffer(5);
|
||||||
|
var bytes1B = new Uint8Array(buffer1B);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes1B[0] = bytes[0];
|
||||||
|
bytes1B[1] = this.checkVisAble(bytes[1] * this._mBrightness + bytes[1]);
|
||||||
|
bytes1B[2] = this.checkVisAble(bytes[2] * this._mBrightness + bytes[2]);
|
||||||
|
bytes1B[3] = this.checkVisAble(bytes[3] * this._mBrightness + bytes[3]);
|
||||||
|
bytes1B[4] = bytes[4];
|
||||||
|
data.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func("", data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkVisAble(input: number) {
|
||||||
|
if (input > 255) {
|
||||||
|
input = 255;
|
||||||
|
}
|
||||||
|
if (input <= 0) {
|
||||||
|
input = 0;
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以24位色图像为例子,每种色彩都可以用0-255,
|
||||||
|
* 一共256种深度来表示。如果我们把它画在一个二维坐标上,
|
||||||
|
* 正好是一条直线。比如我们将像素的色深作为横坐标,输出色深作为纵坐标的画,正好是一条经过原点(0,0)的45度斜线
|
||||||
|
* 那么很容易就可以写出它的直线方程:Out = In * 1 ,系数1就是对比度的概念.如果把条直线加上一个偏移量变成B,那么它的直线方程就成为:
|
||||||
|
* Out = In * 1 + (ab)偏移量(ab)就是亮度的增量。
|
||||||
|
*只要有初中的代数知识就很容易看出它满足一条直线方程:Y= A * X + B。但是,我们这里要处理的情况稍微有些不同,在图像处理中,对比度和亮度要分别对待。不能因为改变而改变亮度,因为我们习惯上把灰色(127,127)这一点作为中心点。
|
||||||
|
*
|
||||||
|
*直线公式修改成:Y=( X - 127 ) * A + B。A表示对比度,B表示亮度增量。
|
||||||
|
* 只要亮度增量 B=0,无论怎么改变对比度 A,该直线始终通过中心点(127,127),也就是说改变对比度的同时,亮度没有改变
|
||||||
|
*
|
||||||
|
*_mContrast value ranges from 0.0 to 4.0, with 1.0 as the normal level
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export class ContrastFilterTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private _mContrast: number;
|
||||||
|
|
||||||
|
constructor(contrast: number) {
|
||||||
|
this._mContrast = contrast;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return "ContrastFilterTransformation:" + this._mContrast;
|
||||||
|
}
|
||||||
|
|
||||||
|
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";ContrastFilterTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";ContrastFilterTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
|
||||||
|
let imageInfo = await imageSource.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("ContrastFilterTransformation The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = await imageSource.createPixelMap(options);
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
|
||||||
|
for (let w = 0;w <= targetWidth; w++) {
|
||||||
|
for (let h = 0;h <= targetHeight; h++) {
|
||||||
|
var buffer = new ArrayBuffer(5);
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var bytes = new Uint8Array(buffer);
|
||||||
|
var buffer1B = new ArrayBuffer(5);
|
||||||
|
var bytes1B = new Uint8Array(buffer1B);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let brightness = 0; //亮度的偏移量,可以默认0
|
||||||
|
|
||||||
|
bytes1B[0] = bytes[0];
|
||||||
|
bytes1B[1] = this.checkVisAble((bytes[1] - 127) * this._mContrast + brightness + 127);
|
||||||
|
bytes1B[2] = this.checkVisAble((bytes[2] - 127) * this._mContrast + brightness + 127);
|
||||||
|
bytes1B[3] = this.checkVisAble((bytes[3] - 127) * this._mContrast + brightness + 127);
|
||||||
|
bytes1B[4] = bytes[4];
|
||||||
|
data.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func("", data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkVisAble(input: number) {
|
||||||
|
if (input > 255) {
|
||||||
|
input = 255;
|
||||||
|
}
|
||||||
|
if (input <= 0) {
|
||||||
|
input = 0;
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class CropCircleTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private static TAG: string= "CropCircleTransformation";
|
||||||
|
private mCenterX: number= 0;
|
||||||
|
private mCenterY: number= 0;
|
||||||
|
private mRadius: number= 0;
|
||||||
|
private mTransform_pixelMap: any;
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return CropCircleTransformation.TAG + ";mCenterX:" + this.mCenterX
|
||||||
|
+ ";mCenterY:" + this.mCenterY
|
||||||
|
+ ";mRadius:" + this.mRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.error(Constants.PROJECT_TAG + CropCircleTransformation.TAG + " buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + CropCircleTransformation.TAG + " buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
var that = this;
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
that.updatePixelMapSize(imageSource, targetWidth, targetHeight, func);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private updatePixelMapSize(imageSource: any, outWith: number, outHeight: number, func?: AsyncTransform<PixelMap>) {
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: outWith,
|
||||||
|
height: outHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then(p => {
|
||||||
|
this.transformCircle(p, func);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(Constants.PROJECT_TAG + CropCircleTransformation.TAG + " transform e:" + e);
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + CropCircleTransformation.TAG + "e" + e, null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private async transformCircle(p: PixelMap, func?: AsyncTransform<PixelMap>) {
|
||||||
|
this.mTransform_pixelMap = p;
|
||||||
|
let imageInfo = await this.mTransform_pixelMap.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("CropCircleTransformation The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var height = size.height;
|
||||||
|
var width = size.width;
|
||||||
|
this.mRadius = 0;
|
||||||
|
if (width > height) {
|
||||||
|
this.mRadius = height / 2;
|
||||||
|
} else {
|
||||||
|
this.mRadius = width / 2;
|
||||||
|
}
|
||||||
|
this.mCenterX = width / 2;
|
||||||
|
this.mCenterY = height / 2;
|
||||||
|
|
||||||
|
let writePromise;
|
||||||
|
|
||||||
|
for (var h = 0;h <= height; h++) {
|
||||||
|
for (var w = 0;w <= width; w++) {
|
||||||
|
if (this.isContainsCircle(w, h)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var buffer1 = new ArrayBuffer(5);
|
||||||
|
var bytes1 = new Uint8Array(buffer1);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0;j < 5; j++) {
|
||||||
|
bytes1[j] = 0;
|
||||||
|
}
|
||||||
|
this.mTransform_pixelMap.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (func) {
|
||||||
|
func("", this.mTransform_pixelMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isContainsCircle(x: number, y: number): boolean {
|
||||||
|
var a = Math.pow((this.mCenterX - x), 2);
|
||||||
|
var b = Math.pow((this.mCenterY - y), 2);
|
||||||
|
var c = Math.sqrt((a + b));
|
||||||
|
return c <= this.mRadius;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,220 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class CropCircleWithBorderTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private static TAG: string= "CropCircleTransformation";
|
||||||
|
private mTransform_pixelMap: any;
|
||||||
|
private mBorderSize: number= 5;
|
||||||
|
private mCenterX: number= 0;
|
||||||
|
private mCenterY: number= 0;
|
||||||
|
private mRadius: number= 0;
|
||||||
|
private mRColor: number= 0;
|
||||||
|
private mGColor: number= 0;
|
||||||
|
private mBColor: number= 0;
|
||||||
|
|
||||||
|
constructor(border_size: number, value: {
|
||||||
|
r_color?: number,
|
||||||
|
g_color?: number,
|
||||||
|
b_color?: number,
|
||||||
|
}) {
|
||||||
|
this.mRColor = value.g_color;
|
||||||
|
this.mGColor = value.g_color;
|
||||||
|
this.mBColor = value.b_color;
|
||||||
|
this.mBorderSize = border_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return CropCircleWithBorderTransformation.TAG + ";mBorderSize:" + this.mBorderSize
|
||||||
|
+ ";mCenterX:" + this.mCenterX
|
||||||
|
+ ";mCenterY:" + this.mCenterY
|
||||||
|
+ ";mRadius:" + this.mRadius
|
||||||
|
+ ";mRColor:" + this.mRColor
|
||||||
|
+ ";mGColor:" + this.mGColor
|
||||||
|
+ ";mBColor:" + this.mBColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
var that = this;
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
that.updatePixelMapSize(imageSource, targetWidth, targetHeight, func);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private updatePixelMapSize(imageSource: any, outWith: number, outHeight: number, func?: AsyncTransform<PixelMap>) {
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: outWith,
|
||||||
|
height: outHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((pixelMap) => {
|
||||||
|
this.transformPixelMap(pixelMap, outWith, outHeight, func);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation e:" + e);
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation e:" + e, null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private async transformPixelMap(pixelMap: PixelMap, width: number, height: number, func?: AsyncTransform<PixelMap>) {
|
||||||
|
this.mTransform_pixelMap = pixelMap;
|
||||||
|
this.mRadius = 0;
|
||||||
|
if (width > height) {
|
||||||
|
this.mRadius = height / 2;
|
||||||
|
} else {
|
||||||
|
this.mRadius = width / 2;
|
||||||
|
}
|
||||||
|
this.mCenterX = width / 2;
|
||||||
|
this.mCenterY = height / 2;
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
for (let h = 0;h <= height; h++) {
|
||||||
|
for (let w = 0;w <= width; w++) {
|
||||||
|
//不在大圆之内的设置透明
|
||||||
|
//在大圆与小圆之间的 设置rgb值
|
||||||
|
//小圆之内的不变
|
||||||
|
let isSmallCircle: boolean = this.isContainsSmallCircle(w, h);
|
||||||
|
let isBigCircle: boolean = this.isContainsCircle(w, h);
|
||||||
|
if (isSmallCircle) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isBigCircle) {
|
||||||
|
//设置透明
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var buffer1B = new ArrayBuffer(5);
|
||||||
|
var bytes1B = new Uint8Array(buffer1B);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0;j < 5; j++) {
|
||||||
|
bytes1B[j] = 0;
|
||||||
|
}
|
||||||
|
this.mTransform_pixelMap.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
} else {
|
||||||
|
//设置broke
|
||||||
|
var buffer = new ArrayBuffer(5);
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.mTransform_pixelMap.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var bytes = new Uint8Array(buffer);
|
||||||
|
var buffer1 = new ArrayBuffer(5);
|
||||||
|
var bytes1 = new Uint8Array(buffer1);
|
||||||
|
var writePositionRen = {
|
||||||
|
pixels: buffer1,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0;j < 5; j++) {
|
||||||
|
if (j == 1 && this.mBColor > 0) {
|
||||||
|
bytes1[j] = this.mBColor;
|
||||||
|
} else if (j == 2 && this.mGColor > 0) {
|
||||||
|
bytes1[j] = this.mGColor;
|
||||||
|
} else if (j == 3 && this.mRColor > 0) {
|
||||||
|
bytes1[j] = this.mRColor;
|
||||||
|
} else {
|
||||||
|
bytes1[j] = bytes[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.mTransform_pixelMap.writePixels(writePositionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (func) {
|
||||||
|
func("", this.mTransform_pixelMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isContainsCircle(x: number, y: number): boolean {
|
||||||
|
var a = Math.pow((this.mCenterX - x), 2);
|
||||||
|
var b = Math.pow((this.mCenterY - y), 2);
|
||||||
|
var c = Math.sqrt((a + b));
|
||||||
|
return c <= this.mRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
isContainsSmallCircle(x: number, y: number): boolean {
|
||||||
|
var a = Math.pow((this.mCenterX - x), 2);
|
||||||
|
var b = Math.pow((this.mCenterY - y), 2);
|
||||||
|
var c = Math.sqrt((a + b));
|
||||||
|
return c <= (this.mRadius - this.mBorderSize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class CropSquareTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private static TAG: string= "CropSquareTransformation";
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return CropSquareTransformation.TAG + ";CropSquareTransformation:" + this;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";CropSquareTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";CropSquareTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.squareCrop(buf, request, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
squareCrop(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
imageSource.getImageInfo()
|
||||||
|
.then((p) => {
|
||||||
|
var pw = p.size.width;
|
||||||
|
var ph = p.size.height;
|
||||||
|
var outWidth = request.size.width;
|
||||||
|
var outHeight = request.size.height;
|
||||||
|
if (pw < outWidth) {
|
||||||
|
outWidth = pw;
|
||||||
|
}
|
||||||
|
if (ph < outHeight) {
|
||||||
|
outHeight = ph;
|
||||||
|
}
|
||||||
|
var targetSize = outWidth > outHeight ? outHeight : outWidth;
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
rotate: 0,
|
||||||
|
desiredSize: {
|
||||||
|
width: outWidth,
|
||||||
|
height: outHeight
|
||||||
|
},
|
||||||
|
desiredRegion: { size: { width: targetSize, height: targetSize },
|
||||||
|
x: pw / 2 - targetSize / 2,
|
||||||
|
y: ph / 2 - targetSize / 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then(data => {
|
||||||
|
if (func) {
|
||||||
|
func("", data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";CropSquareTransformation e:" + e, null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";CropSquareTransformation error:" + error, null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class CropTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private static TAG: string= "CropCircleTransformation";
|
||||||
|
private mWidth: number;
|
||||||
|
private mHeight: number;
|
||||||
|
private mCropType: CropType= CropType.CENTER;
|
||||||
|
|
||||||
|
constructor(width: number, height: number, cropType?: CropType) {
|
||||||
|
this.mWidth = width;
|
||||||
|
this.mHeight = height;
|
||||||
|
this.mCropType = cropType;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return CropTransformation.TAG + ";mWidth:" + this.mWidth
|
||||||
|
+ ";mHeight:" + this.mHeight
|
||||||
|
+ ";mCropType:" + this.mCropType;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";CropTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";CropTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
|
||||||
|
this.mWidth = this.mWidth == 0 ? pixelMapWidth : this.mWidth;
|
||||||
|
this.mHeight = this.mHeight == 0 ? pixelMapHeight : this.mHeight;
|
||||||
|
|
||||||
|
var scaleX = this.mWidth / pixelMapWidth;
|
||||||
|
var scaleY = this.mHeight / pixelMapHeight;
|
||||||
|
var scale = Math.max(scaleX, scaleY);
|
||||||
|
|
||||||
|
var scaledWidth = scale * pixelMapWidth;
|
||||||
|
var scaledHeight = scale * pixelMapHeight;
|
||||||
|
var xx = (this.mWidth - scaledWidth) / 2;
|
||||||
|
var yy = Math.abs(this.getTop(pixelMapHeight));
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredRegion: { size: { width: this.mWidth, height: this.mHeight },
|
||||||
|
x: xx,
|
||||||
|
y: yy,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((data) => {
|
||||||
|
func("", data);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||||
|
func(e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTop(scaledHeight: number): number{
|
||||||
|
switch (this.mCropType.valueOf()) {
|
||||||
|
case CropType.TOP.valueOf():
|
||||||
|
return 0;
|
||||||
|
case CropType.CENTER.valueOf():
|
||||||
|
return (this.mHeight - scaledHeight) / 2;
|
||||||
|
case CropType.BOTTOM.valueOf():
|
||||||
|
return this.mHeight - scaledHeight;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CropType {
|
||||||
|
TOP,
|
||||||
|
CENTER,
|
||||||
|
BOTTOM
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class GrayscaleTransformation implements BaseTransform<PixelMap> {
|
||||||
|
getName() {
|
||||||
|
return "GrayscaleTransformation:" + this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";GrayscaleTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";GrayscaleTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
|
||||||
|
let imageInfo = await imageSource.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("GrayscaleTransformation The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data = await imageSource.createPixelMap(options);
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
for (let w = 0;w <= targetWidth; w++) {
|
||||||
|
for (let h = 0;h <= targetHeight; h++) {
|
||||||
|
var buffer = new ArrayBuffer(5);
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var bytes = new Uint8Array(buffer);
|
||||||
|
var buffer1B = new ArrayBuffer(5);
|
||||||
|
var bytes1B = new Uint8Array(buffer1B);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes1B[0] = bytes[0];
|
||||||
|
bytes1B[1] = this.grayscale(bytes[3], bytes[2], bytes[1]);
|
||||||
|
bytes1B[2] = this.grayscale(bytes[3], bytes[2], bytes[1]);
|
||||||
|
bytes1B[3] = this.grayscale(bytes[3], bytes[2], bytes[1]);
|
||||||
|
bytes1B[4] = bytes[4];
|
||||||
|
data.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func('',data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将读取的像素点的rgb值,全部灰度化,得到灰度图片(黑白图片)加权平均法
|
||||||
|
*/
|
||||||
|
private grayscale(r: number, g: number, b: number): number{
|
||||||
|
return (r * 28 + g * 151 + b * 77) >> 8;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Image inversion is particularly useful for enhancing white or gray detail in
|
||||||
|
* dark areas of an embedded image, especially when black areas dominate in size.The formula for image inversion is as follows:
|
||||||
|
* Reverse Formula
|
||||||
|
* s=L-l-r;
|
||||||
|
* Where, s is the gray level value of a point in the inverted target image, r is the gray level value of the corresponding point in the original image, and L is the number of gray levels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class InvertFilterTransformation implements BaseTransform<PixelMap> {
|
||||||
|
getName() {
|
||||||
|
return "InvertFilterTransformation";
|
||||||
|
}
|
||||||
|
|
||||||
|
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";InvertFilterTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";InvertFilterTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
|
||||||
|
let imageInfo = await imageSource.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("InvertFilterTransformation The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = await imageSource.createPixelMap(options);
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
|
||||||
|
for (let w = 0;w <= targetWidth; w++) {
|
||||||
|
for (let h = 0;h <= targetHeight; h++) {
|
||||||
|
var buffer = new ArrayBuffer(5);
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var bytes = new Uint8Array(buffer);
|
||||||
|
|
||||||
|
var buffer1B = new ArrayBuffer(5);
|
||||||
|
var bytes1B = new Uint8Array(buffer1B);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes1B[0] = bytes[0];
|
||||||
|
bytes1B[1] = this.checkVisAble(255 - bytes[1]);
|
||||||
|
bytes1B[2] = this.checkVisAble(255 - bytes[2]);
|
||||||
|
bytes1B[3] = this.checkVisAble(255 - bytes[3]);
|
||||||
|
bytes1B[4] = bytes[4];
|
||||||
|
data.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func("", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkVisAble(input: number) {
|
||||||
|
if (input > 255) {
|
||||||
|
input = 255;
|
||||||
|
}
|
||||||
|
if (input <= 0) {
|
||||||
|
input = 0;
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
import {pixelUtils} from "../utils/PixelUtils"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a Pixelation effect to the image.
|
||||||
|
* The pixel with a default of 10.0.
|
||||||
|
*/
|
||||||
|
export class PixelationFilterTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private _mPixel: number= 10.0;
|
||||||
|
|
||||||
|
constructor(pixel?: number) {
|
||||||
|
if (pixel) {
|
||||||
|
this._mPixel = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return "PixelationFilterTransformation" + this._mPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";PixelationFilterTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";PixelationFilterTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((data) => {
|
||||||
|
pixelUtils.pixel(data, this._mPixel, func);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||||
|
func(e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class RotateImageTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private mDegreesToRotate: number;
|
||||||
|
|
||||||
|
constructor(degreesToRotate: number) {
|
||||||
|
this.mDegreesToRotate = degreesToRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return "RotateImageTransformation" + ";degreesToRotate:" + this.mDegreesToRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";RotateImageTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";RotateImageTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
rotate: this.mDegreesToRotate%360,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((data) => {
|
||||||
|
func("", data);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||||
|
func(e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {ArcPoint} from "../entry/ArcPoint.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import {TransformUtils} from "../transform/TransformUtils.ets"
|
||||||
|
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
export class RoundedCornersTransformation implements BaseTransform<PixelMap> {
|
||||||
|
private mTop_left: number= 0;
|
||||||
|
private mTop_right: number= 0;
|
||||||
|
private mBottom_left: number= 0;
|
||||||
|
private mBottom_right: number= 0;
|
||||||
|
private mTransform_pixelMap: any;
|
||||||
|
private mPoint: ArcPoint[];
|
||||||
|
|
||||||
|
constructor(value: {
|
||||||
|
top_left?: number,
|
||||||
|
top_right?: number,
|
||||||
|
bottom_left?: number,
|
||||||
|
bottom_right?: number
|
||||||
|
}) {
|
||||||
|
this.mTop_left = value.top_left;
|
||||||
|
this.mTop_right = value.top_right;
|
||||||
|
this.mBottom_left = value.bottom_left;
|
||||||
|
this.mBottom_right = value.bottom_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return "RoundedCornersTransformation" + ";mTop_left:" + this.mTop_left
|
||||||
|
+ ";mTop_right:" + this.mTop_right
|
||||||
|
+ ";mBottom_left:" + this.mBottom_left
|
||||||
|
+ ";mBottom_right:" + this.mBottom_right
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";RoundedCornersTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";RoundedCornersTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
var that = this;
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
that.transformPixelMap(imageSource, targetWidth, targetHeight, func);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private transformPixelMap(imageSource: any, outWith: number, outHeight: number, func?: AsyncTransform<PixelMap>) {
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: outWith,
|
||||||
|
height: outHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((pixelMap) => {
|
||||||
|
this.mTransform_pixelMap = pixelMap;
|
||||||
|
this.mTransform_pixelMap.getImageInfo()
|
||||||
|
.then((data) => {
|
||||||
|
let width = data.size.width;
|
||||||
|
let height = data.size.height;
|
||||||
|
if (this.mTop_left > 0) {
|
||||||
|
this.top_left_corners();
|
||||||
|
}
|
||||||
|
if (this.mTop_right > 0) {
|
||||||
|
this.top_right_corners(width);
|
||||||
|
}
|
||||||
|
if (this.mBottom_left > 0) {
|
||||||
|
this.bottom_left_corners(width, height);
|
||||||
|
}
|
||||||
|
if (this.mBottom_right > 0) {
|
||||||
|
this.bottom_right_corners(width, height);
|
||||||
|
}
|
||||||
|
if (func) {
|
||||||
|
func("", this.mTransform_pixelMap);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(Constants.PROJECT_TAG + "RoundedCornersTransformation error:" + error);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||||
|
if (func) {
|
||||||
|
func(e, null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private top_left_corners() {
|
||||||
|
this.mPoint = new Array<ArcPoint>();
|
||||||
|
for (var time = 180; time < 270; time++) {
|
||||||
|
var hudu = (2 * Math.PI / 360) * time;
|
||||||
|
var x = this.mTop_left + Math.sin(hudu) * this.mTop_left;
|
||||||
|
var y = this.mTop_left + Math.cos(hudu) * this.mTop_left;
|
||||||
|
this.mPoint.push(new ArcPoint(x, y));
|
||||||
|
}
|
||||||
|
this.hand_pixel_point(this.mPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private top_right_corners(width: number) {
|
||||||
|
this.mPoint = new Array<ArcPoint>();
|
||||||
|
for (var time = 0; time < 90; time++) {
|
||||||
|
var hudu = (2 * Math.PI / 360) * time;
|
||||||
|
var x = (width - this.mTop_right) + Math.cos(hudu) * this.mTop_right;
|
||||||
|
var y = this.mTop_right - Math.sin(hudu) * this.mTop_right;
|
||||||
|
this.mPoint.push(new ArcPoint(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hand_right_pixel_point(this.mPoint, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bottom_left_corners(width: number, height: number) {
|
||||||
|
this.mPoint = new Array<ArcPoint>();
|
||||||
|
for (var time = 90; time < 180; time++) {
|
||||||
|
var hudu = (2 * Math.PI / 360) * time;
|
||||||
|
var x = this.mBottom_left + Math.cos(hudu) * this.mBottom_left;
|
||||||
|
var y = height - this.mBottom_left + Math.sin(hudu) * this.mBottom_left;
|
||||||
|
this.mPoint.push(new ArcPoint(x, y));
|
||||||
|
}
|
||||||
|
this.hand_pixel_point(this.mPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bottom_right_corners(width: number, height: number) {
|
||||||
|
this.mPoint = new Array<ArcPoint>();
|
||||||
|
for (var time = 0; time < 90; time++) {
|
||||||
|
var hudu = (2 * Math.PI / 360) * time;
|
||||||
|
var x = width - this.mBottom_right + Math.cos(hudu) * this.mBottom_right;
|
||||||
|
var y = height - this.mBottom_right + Math.sin(hudu) * this.mBottom_right;
|
||||||
|
this.mPoint.push(new ArcPoint(x, y));
|
||||||
|
}
|
||||||
|
this.hand_right_pixel_point(this.mPoint, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
private hand_pixel_point(points: ArcPoint[]) {
|
||||||
|
for (var index = 0; index < points.length; index++) {
|
||||||
|
const element = points[index];
|
||||||
|
let x = element.getX();
|
||||||
|
let y = element.getY();
|
||||||
|
|
||||||
|
for (var i = 0; i <= x; i++) {
|
||||||
|
var buffer1 = new ArrayBuffer(5);
|
||||||
|
var bytes1 = new Uint8Array(buffer1);
|
||||||
|
var writePositionRen = {
|
||||||
|
pixels: buffer1,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: i,
|
||||||
|
y: y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0;j < 5; j++) {
|
||||||
|
bytes1[j] = 0;
|
||||||
|
}
|
||||||
|
this.mTransform_pixelMap.writePixels(writePositionRen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private hand_right_pixel_point(points: ArcPoint[], width: number) {
|
||||||
|
for (var index = 0; index < points.length; index++) {
|
||||||
|
const element = points[index];
|
||||||
|
let x = element.getX();
|
||||||
|
let y = element.getY();
|
||||||
|
|
||||||
|
for (var i = x; i <= width; i++) {
|
||||||
|
var buffer1 = new ArrayBuffer(5);
|
||||||
|
var bytes1 = new Uint8Array(buffer1);
|
||||||
|
var writePositionRen = {
|
||||||
|
pixels: buffer1,
|
||||||
|
offset: 0,
|
||||||
|
stride: 4,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: i,
|
||||||
|
y: y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0;j < 5; j++) {
|
||||||
|
bytes1[j] = 0;
|
||||||
|
}
|
||||||
|
this.mTransform_pixelMap.writePixels(writePositionRen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from "../transform/BaseTransform.ets"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform.ets"
|
||||||
|
import {Constants} from "../constants/Constants.ets"
|
||||||
|
import {RequestOption} from "../../glide/RequestOption.ets"
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a simple sepia effect.
|
||||||
|
* <p>
|
||||||
|
* The intensity with a default of 1.0.
|
||||||
|
*/
|
||||||
|
export class SepiaFilterTransformation implements BaseTransform<PixelMap> {
|
||||||
|
getName() {
|
||||||
|
return "SepiaFilterTransformation";
|
||||||
|
}
|
||||||
|
|
||||||
|
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
console.log(Constants.PROJECT_TAG + ";SepiaFilterTransformation buf is empty");
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ";SepiaFilterTransformation buf is empty", null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
|
||||||
|
let imageInfo = await imageSource.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("SepiaFilterTransformation The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data = await imageSource.createPixelMap(options);
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
for (let w = 0;w <= targetWidth; w++) {
|
||||||
|
for (let h = 0;h <= targetHeight; h++) {
|
||||||
|
var buffer = new ArrayBuffer(5);
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var bytes = new Uint8Array(buffer);
|
||||||
|
var buffer1B = new ArrayBuffer(5);
|
||||||
|
var bytes1B = new Uint8Array(buffer1B);
|
||||||
|
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes1B[0] = bytes[0];
|
||||||
|
bytes1B[1] = this.checkVisAble(this.colorBlend(this.noise()
|
||||||
|
, (bytes[3] * 0.272) + (bytes[2] * 0.534) + (bytes[1] * 0.131)
|
||||||
|
, bytes[1]));
|
||||||
|
bytes1B[2] = this.checkVisAble(this.colorBlend(this.noise()
|
||||||
|
, (bytes[3] * 0.349) + (bytes[2] * 0.686) + (bytes[1] * 0.168)
|
||||||
|
, bytes[2]));
|
||||||
|
bytes1B[3] = this.checkVisAble(this.colorBlend(this.noise()
|
||||||
|
, (bytes[3] * 0.393) + (bytes[2] * 0.769) + (bytes[1] * 0.189)
|
||||||
|
, bytes[3]));
|
||||||
|
bytes1B[4] = bytes[4];
|
||||||
|
|
||||||
|
data.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func("", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkVisAble(input: number) {
|
||||||
|
if (input > 255) {
|
||||||
|
input = 255;
|
||||||
|
}
|
||||||
|
if (input <= 0) {
|
||||||
|
input = 0;
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
private colorBlend(scale: number, dest: number, src: number): number {
|
||||||
|
return (scale * dest + (1.0 - scale) * src);
|
||||||
|
}
|
||||||
|
|
||||||
|
private noise(): number {
|
||||||
|
return Math.random() * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from '../transform/BaseTransform.ets'
|
||||||
|
import {AsyncTransform} from '../transform/AsyncTransform.ets'
|
||||||
|
import {Constants} from '../constants/Constants.ets'
|
||||||
|
import {RequestOption} from '../../glide/RequestOption.ets'
|
||||||
|
import {TransformUtils} from '../transform/TransformUtils.ets'
|
||||||
|
import image from '@ohos.multimedia.image'
|
||||||
|
import {CalculatePixelUtils} from '../utils/CalculatePixelUtils'
|
||||||
|
|
||||||
|
export class SketchFilterTransformation implements BaseTransform<PixelMap> {
|
||||||
|
getName() {
|
||||||
|
return 'SketchFilterTransformation';
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
throw new Error(Constants.PROJECT_TAG + ';SketchFilterTransformation buf is empty');
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ';SketchFilterTransformation buf is empty', null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
TransformUtils.getPixelMapSize(imageSource, (error, size: {
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}) => {
|
||||||
|
if (!size) {
|
||||||
|
func(error, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pixelMapWidth = size.width;
|
||||||
|
var pixelMapHeight = size.height;
|
||||||
|
var targetWidth = request.size.width;
|
||||||
|
var targetHeight = request.size.height;
|
||||||
|
if (pixelMapWidth < targetWidth) {
|
||||||
|
targetWidth = pixelMapWidth;
|
||||||
|
}
|
||||||
|
if (pixelMapHeight < targetHeight) {
|
||||||
|
targetHeight = pixelMapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: {
|
||||||
|
width: targetWidth,
|
||||||
|
height: targetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.createPixelMap(options)
|
||||||
|
.then((data) => {
|
||||||
|
CalculatePixelUtils.sketch(data, func);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
func(e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {AsyncTransform} from '../transform/AsyncTransform.ets'
|
||||||
|
import image from '@ohos.multimedia.image'
|
||||||
|
|
||||||
|
export class TransformUtils {
|
||||||
|
static centerCrop(buf: ArrayBuffer, outWidth: number, outHeihgt: number,
|
||||||
|
callback?: AsyncTransform<Promise<PixelMap>>) {
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
imageSource.getImageInfo()
|
||||||
|
.then((p) => {
|
||||||
|
var sw;
|
||||||
|
var sh;
|
||||||
|
var scale;
|
||||||
|
var pw = p.size.width;
|
||||||
|
var ph = p.size.height;
|
||||||
|
if (pw == outWidth && ph == outHeihgt) {
|
||||||
|
sw = outWidth;
|
||||||
|
sh = outHeihgt;
|
||||||
|
} else {
|
||||||
|
if (pw * outHeihgt > outWidth * ph) {
|
||||||
|
scale = outHeihgt / ph;
|
||||||
|
} else {
|
||||||
|
scale = outWidth / pw;
|
||||||
|
}
|
||||||
|
sw = pw * scale;
|
||||||
|
sh = ph * scale;
|
||||||
|
}
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
rotate: 0,
|
||||||
|
desiredRegion: { size: { width: sw, height: sh },
|
||||||
|
x: pw / 2 - sw / 2,
|
||||||
|
y: ph / 2 - sh / 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
callback('', imageSource.createPixelMap(options));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
callback(error, null);
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static rotateImage(buf: ArrayBuffer, degreesToRotate: number): Promise<PixelMap>{
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
rotate: degreesToRotate
|
||||||
|
}
|
||||||
|
return imageSource.createPixelMap(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
static centerInside(buf: ArrayBuffer, outWidth: number, outHeihgt: number,
|
||||||
|
callback?: AsyncTransform<Promise<PixelMap>>) {
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
imageSource.getImageInfo()
|
||||||
|
.then((p) => {
|
||||||
|
var pw = p.size.width;
|
||||||
|
var ph = p.size.height;
|
||||||
|
if (pw <= outWidth && ph <= outHeihgt) {
|
||||||
|
callback('', imageSource.createPixelMap());
|
||||||
|
} else {
|
||||||
|
this.fitCenter(buf, outWidth, outHeihgt, callback);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
callback(error, null);
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static fitCenter(buf: ArrayBuffer, outWidth: number, outHeihgt: number
|
||||||
|
, callback?: AsyncTransform<Promise<PixelMap>>) {
|
||||||
|
var imageSource = image.createImageSource(buf);
|
||||||
|
imageSource.getImageInfo()
|
||||||
|
.then((p) => {
|
||||||
|
var pw = p.size.width;
|
||||||
|
var ph = p.size.height;
|
||||||
|
var widthPercentage = outWidth / pw;
|
||||||
|
var heightPercentage = outHeihgt / ph;
|
||||||
|
var minPercentage = Math.min(widthPercentage, heightPercentage);
|
||||||
|
|
||||||
|
var targetWidth = Math.round(minPercentage * pw);
|
||||||
|
var targetHeight = Math.round(minPercentage * ph);
|
||||||
|
|
||||||
|
if (pw == targetWidth && ph == targetHeight) {
|
||||||
|
targetWidth = pw;
|
||||||
|
targetHeight = ph;
|
||||||
|
} else {
|
||||||
|
targetWidth = minPercentage * pw;
|
||||||
|
targetHeight = minPercentage * ph;
|
||||||
|
}
|
||||||
|
var options = {
|
||||||
|
editable: true,
|
||||||
|
rotate: 0,
|
||||||
|
desiredSize: { width: targetWidth, height: targetHeight }
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
callback('', imageSource.createPixelMap(options));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
if (callback) {
|
||||||
|
callback(e, null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static getPixelMapSize(imageSource: any, func: AsyncTransform<{
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
}>) {
|
||||||
|
if (!imageSource) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
imageSource.getImageInfo((err, value) => {
|
||||||
|
if (err) {
|
||||||
|
func(err, null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pWidth = value.size.width;
|
||||||
|
var pHeight = value.size.height;
|
||||||
|
func('', { width: pWidth, height: pHeight });
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from '../BaseTransform.ets'
|
||||||
|
import {AsyncTransform} from '../AsyncTransform.ets'
|
||||||
|
import {Constants} from '../../constants/Constants.ets'
|
||||||
|
import {TransformUtils} from '../TransformUtils.ets'
|
||||||
|
import {RequestOption} from '../../../glide/RequestOption.ets'
|
||||||
|
|
||||||
|
export class CenterCrop implements BaseTransform<PixelMap> {
|
||||||
|
getName() {
|
||||||
|
return 'CenterCrop:' + this;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
throw new Error(Constants.PROJECT_TAG + ';CenterCrop buf is empty');
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ';CenterCrop buf is empty', null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TransformUtils.centerCrop(buf, request.size.width, request.size.height, (error, data) => {
|
||||||
|
data.then(p => {
|
||||||
|
func('', p);
|
||||||
|
}).catch(e => {
|
||||||
|
func(Constants.PROJECT_TAG + ';CenterCrop error:' + e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from '../BaseTransform.ets'
|
||||||
|
import {AsyncTransform} from '../AsyncTransform.ets'
|
||||||
|
import {Constants} from '../../constants/Constants.ets'
|
||||||
|
import {TransformUtils} from '../TransformUtils.ets'
|
||||||
|
import {RequestOption} from '../../../glide/RequestOption.ets'
|
||||||
|
|
||||||
|
export class CenterInside implements BaseTransform<PixelMap> {
|
||||||
|
getName() {
|
||||||
|
return 'CenterInside:' + this;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
throw new Error(Constants.PROJECT_TAG + ';CenterInside buf is empty');
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ';CenterInside buf is empty', null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TransformUtils.centerInside(buf, request.size.width, request.size.height, (error, data) => {
|
||||||
|
data.then(p => {
|
||||||
|
func('', p);
|
||||||
|
}).catch(e => {
|
||||||
|
func(Constants.PROJECT_TAG + ';CenterInside error:' + e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseTransform} from '../BaseTransform.ets'
|
||||||
|
import {AsyncTransform} from '../AsyncTransform.ets'
|
||||||
|
import {Constants} from '../../constants/Constants.ets'
|
||||||
|
import {TransformUtils} from '../TransformUtils.ets'
|
||||||
|
import {RequestOption} from '../../../glide/RequestOption.ets'
|
||||||
|
|
||||||
|
export class FitCenter implements BaseTransform<PixelMap> {
|
||||||
|
getName() {
|
||||||
|
return 'FitCenter:' + this;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||||
|
if (!buf || buf.byteLength <= 0) {
|
||||||
|
throw new Error(Constants.PROJECT_TAG + ';FitCenter buf is empty');
|
||||||
|
if (func) {
|
||||||
|
func(Constants.PROJECT_TAG + ';FitCenter buf is empty', null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TransformUtils.fitCenter(buf, request.size.width, request.size.height, (error, data) => {
|
||||||
|
data.then(p => {
|
||||||
|
func('', p);
|
||||||
|
}).catch(e => {
|
||||||
|
func(Constants.PROJECT_TAG + ';FitCenter error:' + e, null);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,310 @@
|
||||||
|
import {PixelEntry} from "../entry/PixelEntry"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform"
|
||||||
|
import {ColorUtils} from "./ColorUtils"
|
||||||
|
|
||||||
|
export namespace CalculatePixelUtils {
|
||||||
|
export async function sketch(p: any, func: AsyncTransform<PixelMap>) {
|
||||||
|
let imageInfo = await p.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("sketch The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pos, row, col, clr: number;
|
||||||
|
let width = size.width;
|
||||||
|
let height = size.height;
|
||||||
|
var pixEntry: Array<PixelEntry> = new Array()
|
||||||
|
var pixSrc: Array<number> = new Array()
|
||||||
|
var pixNvt: Array<number> = new Array()
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
|
||||||
|
for (let h = 0; h < height; h++) {
|
||||||
|
for (let w = 0; w < width; w++) {
|
||||||
|
let buffer = new ArrayBuffer(5);
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: w,
|
||||||
|
y: h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
|
||||||
|
let bytes = new Uint8Array(buffer);
|
||||||
|
let entry = new PixelEntry();
|
||||||
|
entry.a = bytes[0];
|
||||||
|
entry.b = bytes[1];
|
||||||
|
entry.g = bytes[2];
|
||||||
|
entry.r = bytes[3];
|
||||||
|
entry.f = bytes[4];
|
||||||
|
entry.pixel = ColorUtils.rgb(entry.r, entry.g, entry.b);
|
||||||
|
pixEntry.push(entry);
|
||||||
|
pixSrc.push(ColorUtils.rgb(entry.r, entry.g, entry.b));
|
||||||
|
pixNvt.push(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (row = 0; row < height; row++) {
|
||||||
|
for (col = 0; col < width; col++) {
|
||||||
|
pos = row * width + col;
|
||||||
|
pixSrc[pos] = (pixEntry[pos].r + pixEntry[pos].g + pixEntry[pos].b) / 3;
|
||||||
|
pixNvt[pos] = 255 - pixSrc[pos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 对取反的像素进行高斯模糊, 强度可以设置,暂定为5.0
|
||||||
|
gaussGray(pixNvt, 5.0, 5.0, width, height);
|
||||||
|
// 灰度颜色和模糊后像素进行差值运算
|
||||||
|
for (row = 0; row < height; row++) {
|
||||||
|
for (col = 0; col < width; col++) {
|
||||||
|
pos = row * width + col;
|
||||||
|
clr = pixSrc[pos] << 8;
|
||||||
|
clr /= 256 - pixNvt[pos];
|
||||||
|
clr = Math.min(clr, 255);
|
||||||
|
pixSrc[pos] = ColorUtils.rgb(clr, clr, clr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let m = 0;m < height; m++) { //y
|
||||||
|
for (let n = 0;n < width; n++) { //x
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
let buffer1B = new ArrayBuffer(5);
|
||||||
|
let bytes1B = new Uint8Array(buffer1B);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: n,
|
||||||
|
y: m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = m * width + n;
|
||||||
|
bytes1B[0] = pixEntry[m * width + n].a;
|
||||||
|
bytes1B[1] = ColorUtils.blue(pixSrc[index]);
|
||||||
|
bytes1B[2] = ColorUtils.green(pixSrc[index]);
|
||||||
|
bytes1B[3] = ColorUtils.red(pixSrc[index]);
|
||||||
|
bytes1B[4] = pixEntry[m * width + n].f;
|
||||||
|
p.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func("success", p);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function gaussGray(psrc: Array<number>, horz: number, vert: number,
|
||||||
|
width: number, height: number): number {
|
||||||
|
let dst, src, n_p, n_m, d_p, d_m, bd_p, bd_m, val_p, val_m, initial_p, initial_m: Array<number>;
|
||||||
|
let i, j, t, k, row, col, terms, std_dev, sp_p_idx, sp_m_idx, vp_idx, vm_idx: number;
|
||||||
|
let row_stride = width;
|
||||||
|
let max_len = Math.max(width, height);
|
||||||
|
val_p = createIntArray(max_len);
|
||||||
|
val_m = createIntArray(max_len);
|
||||||
|
n_p = createIntArray(5);
|
||||||
|
n_m = createIntArray(5);
|
||||||
|
d_p = createIntArray(5);
|
||||||
|
d_m = createIntArray(5);
|
||||||
|
bd_p = createIntArray(5);
|
||||||
|
bd_m = createIntArray(5);
|
||||||
|
src = createIntArray(max_len);
|
||||||
|
dst = createIntArray(max_len);
|
||||||
|
initial_p = createIntArray(4);
|
||||||
|
initial_m = createIntArray(4);
|
||||||
|
// 垂直方向
|
||||||
|
if (vert > 0.0) {
|
||||||
|
vert = Math.abs(vert) + 1.0;
|
||||||
|
std_dev = Math.sqrt(-(vert * vert) / (2 * Math.log(1.0 / 255.0)));
|
||||||
|
// 初试化常量
|
||||||
|
findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
|
||||||
|
for (col = 0; col < width; col++) {
|
||||||
|
for (k = 0; k < max_len; k++) {
|
||||||
|
val_m[k] = val_p[k] = 0;
|
||||||
|
}
|
||||||
|
for (t = 0; t < height; t++) {
|
||||||
|
src[t] = psrc[t * row_stride + col];
|
||||||
|
}
|
||||||
|
sp_p_idx = 0;
|
||||||
|
sp_m_idx = height - 1;
|
||||||
|
vp_idx = 0;
|
||||||
|
vm_idx = height - 1;
|
||||||
|
initial_p[0] = src[0];
|
||||||
|
initial_m[0] = src[height - 1];
|
||||||
|
for (row = 0; row < height; row++) {
|
||||||
|
terms = (row < 4) ? row : 4;
|
||||||
|
for (i = 0; i <= terms; i++) {
|
||||||
|
val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i]
|
||||||
|
* val_p[vp_idx - i];
|
||||||
|
val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i]
|
||||||
|
* val_m[vm_idx + i];
|
||||||
|
}
|
||||||
|
for (j = i; j <= 4; j++) {
|
||||||
|
val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
|
||||||
|
val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
|
||||||
|
}
|
||||||
|
sp_p_idx++;
|
||||||
|
sp_m_idx--;
|
||||||
|
vp_idx++;
|
||||||
|
vm_idx--;
|
||||||
|
}
|
||||||
|
transferGaussPixels(val_p, val_m, dst, 1, height);
|
||||||
|
for (t = 0; t < height; t++) {
|
||||||
|
psrc[t * row_stride + col] = dst[t];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 水平方向
|
||||||
|
if (horz > 0.0) {
|
||||||
|
horz = Math.abs(horz) + 1.0;
|
||||||
|
if (horz != vert) {
|
||||||
|
std_dev = Math.sqrt(-(horz * horz)
|
||||||
|
/ (2 * Math.log(1.0 / 255.0)));
|
||||||
|
// 初试化常量
|
||||||
|
findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
|
||||||
|
}
|
||||||
|
for (row = 0; row < height; row++) {
|
||||||
|
for (k = 0; k < max_len; k++) {
|
||||||
|
val_m[k] = val_p[k] = 0;
|
||||||
|
}
|
||||||
|
for (t = 0; t < width; t++) {
|
||||||
|
src[t] = psrc[row * row_stride + t];
|
||||||
|
}
|
||||||
|
sp_p_idx = 0;
|
||||||
|
sp_m_idx = width - 1;
|
||||||
|
vp_idx = 0;
|
||||||
|
vm_idx = width - 1;
|
||||||
|
initial_p[0] = src[0];
|
||||||
|
initial_m[0] = src[width - 1];
|
||||||
|
for (col = 0; col < width; col++) {
|
||||||
|
terms = (col < 4) ? col : 4;
|
||||||
|
for (i = 0; i <= terms; i++) {
|
||||||
|
val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i]
|
||||||
|
* val_p[vp_idx - i];
|
||||||
|
val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i]
|
||||||
|
* val_m[vm_idx + i];
|
||||||
|
}
|
||||||
|
for (j = i; j <= 4; j++) {
|
||||||
|
val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
|
||||||
|
val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
|
||||||
|
}
|
||||||
|
sp_p_idx++;
|
||||||
|
sp_m_idx--;
|
||||||
|
vp_idx++;
|
||||||
|
vm_idx--;
|
||||||
|
}
|
||||||
|
transferGaussPixels(val_p, val_m, dst, 1, width);
|
||||||
|
for (t = 0; t < width; t++) {
|
||||||
|
psrc[row * row_stride + t] = dst[t];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findConstants(n_p: Array<number>, n_m: Array<number>, d_p: Array<number>,
|
||||||
|
d_m: Array<number>, bd_p: Array<number>
|
||||||
|
, bd_m: Array<number>, std_dev: number) {
|
||||||
|
let div = Math.sqrt(2 * 3.141593) * std_dev;
|
||||||
|
let x0 = -1.783 / std_dev;
|
||||||
|
let x1 = -1.723 / std_dev;
|
||||||
|
let x2 = 0.6318 / std_dev;
|
||||||
|
let x3 = 1.997 / std_dev;
|
||||||
|
let x4 = 1.6803 / div;
|
||||||
|
let x5 = 3.735 / div;
|
||||||
|
let x6 = -0.6803 / div;
|
||||||
|
let x7 = -0.2598 / div;
|
||||||
|
let i;
|
||||||
|
n_p[0] = x4 + x6;
|
||||||
|
n_p[1] = (Math.exp(x1)
|
||||||
|
* (x7 * Math.sin(x3) - (x6 + 2 * x4) * Math.cos(x3)) + Math
|
||||||
|
.exp(x0) * (x5 * Math.sin(x2) - (2 * x6 + x4) * Math.cos(x2)));
|
||||||
|
n_p[2] = (2
|
||||||
|
* Math.exp(x0 + x1)
|
||||||
|
* ((x4 + x6) * Math.cos(x3) * Math.cos(x2) - x5 * Math.cos(x3)
|
||||||
|
* Math.sin(x2) - x7 * Math.cos(x2) * Math.sin(x3)) + x6
|
||||||
|
* Math.exp(2 * x0) + x4 * Math.exp(2 * x1));
|
||||||
|
n_p[3] = (Math.exp(x1 + 2 * x0)
|
||||||
|
* (x7 * Math.sin(x3) - x6 * Math.cos(x3)) + Math.exp(x0 + 2
|
||||||
|
* x1)
|
||||||
|
* (x5 * Math.sin(x2) - x4 * Math.cos(x2)));
|
||||||
|
n_p[4] = 0.0;
|
||||||
|
d_p[0] = 0.0;
|
||||||
|
d_p[1] = -2 * Math.exp(x1) * Math.cos(x3) - 2 * Math.exp(x0)
|
||||||
|
* Math.cos(x2);
|
||||||
|
d_p[2] = 4 * Math.cos(x3) * Math.cos(x2) * Math.exp(x0 + x1)
|
||||||
|
+ Math.exp(2 * x1) + Math.exp(2 * x0);
|
||||||
|
d_p[3] = -2 * Math.cos(x2) * Math.exp(x0 + 2 * x1) - 2 * Math.cos(x3)
|
||||||
|
* Math.exp(x1 + 2 * x0);
|
||||||
|
d_p[4] = Math.exp(2 * x0 + 2 * x1);
|
||||||
|
for (i = 0; i <= 4; i++) {
|
||||||
|
d_m[i] = d_p[i];
|
||||||
|
}
|
||||||
|
n_m[0] = 0.0;
|
||||||
|
for (i = 1; i <= 4; i++) {
|
||||||
|
n_m[i] = n_p[i] - d_p[i] * n_p[0];
|
||||||
|
}
|
||||||
|
let sum_n_p, sum_n_m, sum_d, a, b: number;
|
||||||
|
sum_n_p = 0.0;
|
||||||
|
sum_n_m = 0.0;
|
||||||
|
sum_d = 0.0;
|
||||||
|
for (i = 0; i <= 4; i++) {
|
||||||
|
sum_n_p += n_p[i];
|
||||||
|
sum_n_m += n_m[i];
|
||||||
|
sum_d += d_p[i];
|
||||||
|
}
|
||||||
|
a = sum_n_p / (1.0 + sum_d);
|
||||||
|
b = sum_n_m / (1.0 + sum_d);
|
||||||
|
for (i = 0; i <= 4; i++) {
|
||||||
|
bd_p[i] = d_p[i] * a;
|
||||||
|
bd_m[i] = d_m[i] * b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferGaussPixels(src1: Array<number>, src2: Array<number>,
|
||||||
|
dest: Array<number>, bytes: number, width: number) {
|
||||||
|
let i, j, k, b, sum: number;
|
||||||
|
let bend = bytes * width;
|
||||||
|
i = j = k = 0;
|
||||||
|
for (b = 0; b < bend; b++) {
|
||||||
|
sum = src1[i++] + src2[j++];
|
||||||
|
if (sum > 255)
|
||||||
|
sum = 255;
|
||||||
|
else if (sum < 0)
|
||||||
|
sum = 0;
|
||||||
|
dest[k++] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createIntArray(len: number): Array<number> {
|
||||||
|
let array = new Array<number>();
|
||||||
|
for (var index = 0; index < len; index++) {
|
||||||
|
array.push(0);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createInt2DArray(first_len: number, second_len: number): Array<Array<number>> {
|
||||||
|
let array = new Array<Array<number>>();
|
||||||
|
for (let f = 0; f < first_len; f++) {
|
||||||
|
let s1 = new Array<number>();
|
||||||
|
for (let s = 0; s < second_len; s++) {
|
||||||
|
s1.push(0);
|
||||||
|
}
|
||||||
|
array.push(s1);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import resmgr from '@ohos.resourceManager'
|
||||||
|
import {DataCallBack} from "../interface/DataCallBack"
|
||||||
|
|
||||||
|
export namespace ColorUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地颜色值解析
|
||||||
|
* ColorUtils.parseColor("color_name",callback)
|
||||||
|
*/
|
||||||
|
export function parseColor(c: string, callback: DataCallBack<string>) {
|
||||||
|
resmgr.getResourceManager()
|
||||||
|
.then(result => {
|
||||||
|
var reColor = 'sys.color.' + c;
|
||||||
|
result.getString($r(reColor)
|
||||||
|
.id, (err, color) => {
|
||||||
|
if (!err) {
|
||||||
|
var cos = JSON.stringify(color);
|
||||||
|
callback.callback(cos)
|
||||||
|
} else {
|
||||||
|
callback.callback(err.message)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
callback.callback(error.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function red(color: number): number {
|
||||||
|
return (color >> 16) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function green(color: number): number {
|
||||||
|
return (color >> 8) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function blue(color: number): number {
|
||||||
|
return color & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function alpha(color: number): number {
|
||||||
|
return color >>> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rgb(red: number, green: number, blue: number): number {
|
||||||
|
return 0xff000000 | (red << 16) | (green << 8) | blue;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,320 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import image from "@ohos.multimedia.image"
|
||||||
|
import {CalculatePixelUtils} from "./CalculatePixelUtils"
|
||||||
|
import {PixelEntry} from "../entry/PixelEntry"
|
||||||
|
import {AsyncTransform} from "../transform/AsyncTransform"
|
||||||
|
import {ColorUtils} from "./ColorUtils"
|
||||||
|
|
||||||
|
|
||||||
|
export namespace fastBlur {
|
||||||
|
|
||||||
|
|
||||||
|
export async function blur(bitmap: any, radius: number, canReuseInBitmap: boolean, func: AsyncTransform<PixelMap>) {
|
||||||
|
|
||||||
|
// Stack Blur v1.0 from
|
||||||
|
// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
|
||||||
|
//
|
||||||
|
// Java Author: Mario Klingemann <mario at quasimondo.com>
|
||||||
|
// http://incubator.quasimondo.com
|
||||||
|
// created Feburary 29, 2004
|
||||||
|
// Android port : Yahel Bouaziz <yahel at kayenko.com>
|
||||||
|
// http://www.kayenko.com
|
||||||
|
// ported april 5th, 2012
|
||||||
|
|
||||||
|
// This is a compromise between Gaussian Blur and Box blur
|
||||||
|
// It creates much better looking blurs than Box Blur, but is
|
||||||
|
// 7x faster than my Gaussian Blur implementation.
|
||||||
|
//
|
||||||
|
// I called it Stack Blur because this describes best how this
|
||||||
|
// filter works internally: it creates a kind of moving stack
|
||||||
|
// of colors whilst scanning through the image. Thereby it
|
||||||
|
// just has to add one new block of color to the right side
|
||||||
|
// of the stack and remove the leftmost color. The remaining
|
||||||
|
// colors on the topmost layer of the stack are either added on
|
||||||
|
// or reduced by one, depending on if they are on the right or
|
||||||
|
// on the left side of the stack.
|
||||||
|
//
|
||||||
|
// If you are using this algorithm in your code please add
|
||||||
|
// the following line:
|
||||||
|
//
|
||||||
|
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
|
||||||
|
if (radius < 1) {
|
||||||
|
func("error,radius must be greater than 1 ", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let imageInfo = await bitmap.getImageInfo();
|
||||||
|
let size = {
|
||||||
|
width: imageInfo.size.width,
|
||||||
|
height: imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size) {
|
||||||
|
func(new Error("fastBlur The image size does not exist."), null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let w = size.width;
|
||||||
|
let h = size.height;
|
||||||
|
var pixEntry: Array<PixelEntry> = new Array()
|
||||||
|
var pix: Array<number> = new Array()
|
||||||
|
|
||||||
|
let readPromise;
|
||||||
|
let writePromise;
|
||||||
|
|
||||||
|
for (let ph = 0; ph < h; ph++) {
|
||||||
|
for (let pw = 0; pw < w; pw++) {
|
||||||
|
let buffer = new ArrayBuffer(5);
|
||||||
|
readPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
var positionRen = {
|
||||||
|
pixels: buffer,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: pw,
|
||||||
|
y: ph
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitmap.readPixels(positionRen, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await readPromise;
|
||||||
|
|
||||||
|
let bytes = new Uint8Array(buffer);
|
||||||
|
let entry = new PixelEntry();
|
||||||
|
entry.a = bytes[0];
|
||||||
|
entry.b = bytes[1];
|
||||||
|
entry.g = bytes[2];
|
||||||
|
entry.r = bytes[3];
|
||||||
|
entry.f = bytes[4];
|
||||||
|
entry.pixel = ColorUtils.rgb(entry.r, entry.g, entry.b);
|
||||||
|
pixEntry.push(entry);
|
||||||
|
pix.push(ColorUtils.rgb(entry.r, entry.g, entry.b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let wm = w - 1;
|
||||||
|
let hm = h - 1;
|
||||||
|
let wh = w * h;
|
||||||
|
let div = radius + radius + 1;
|
||||||
|
|
||||||
|
let r = CalculatePixelUtils.createIntArray(wh);
|
||||||
|
let g = CalculatePixelUtils.createIntArray(wh);
|
||||||
|
let b = CalculatePixelUtils.createIntArray(wh);
|
||||||
|
|
||||||
|
let rsum, gsum, bsum, x, y, i, p, yp, yi, yw: number;
|
||||||
|
let vmin = CalculatePixelUtils.createIntArray(Math.max(w, h));
|
||||||
|
|
||||||
|
let divsum = (div + 1) >> 1;
|
||||||
|
divsum *= divsum;
|
||||||
|
let dv = CalculatePixelUtils.createIntArray(256 * divsum);
|
||||||
|
for (i = 0; i < 256 * divsum; i++) {
|
||||||
|
dv[i] = (i / divsum);
|
||||||
|
}
|
||||||
|
|
||||||
|
yw = yi = 0;
|
||||||
|
let stack = CalculatePixelUtils.createInt2DArray(div, 3);
|
||||||
|
let stackpointer, stackstart, rbs, routsum, goutsum, boutsum, rinsum, ginsum, binsum: number;
|
||||||
|
let sir: Array<number>;
|
||||||
|
let r1 = radius + 1;
|
||||||
|
for (y = 0; y < h; y++) {
|
||||||
|
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||||
|
for (i = -radius; i <= radius; i++) {
|
||||||
|
p = pix[yi + Math.min(wm, Math.max(i, 0))];
|
||||||
|
sir = stack[i + radius];
|
||||||
|
sir[0] = (p & 0xff0000) >> 16;
|
||||||
|
sir[1] = (p & 0x00ff00) >> 8;
|
||||||
|
sir[2] = (p & 0x0000ff);
|
||||||
|
rbs = r1 - Math.abs(i);
|
||||||
|
rsum += sir[0] * rbs;
|
||||||
|
gsum += sir[1] * rbs;
|
||||||
|
bsum += sir[2] * rbs;
|
||||||
|
if (i > 0) {
|
||||||
|
rinsum += sir[0];
|
||||||
|
ginsum += sir[1];
|
||||||
|
binsum += sir[2];
|
||||||
|
} else {
|
||||||
|
routsum += sir[0];
|
||||||
|
goutsum += sir[1];
|
||||||
|
boutsum += sir[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stackpointer = radius;
|
||||||
|
|
||||||
|
for (x = 0; x < w; x++) {
|
||||||
|
|
||||||
|
r[yi] = dv[rsum];
|
||||||
|
g[yi] = dv[gsum];
|
||||||
|
b[yi] = dv[bsum];
|
||||||
|
|
||||||
|
rsum -= routsum;
|
||||||
|
gsum -= goutsum;
|
||||||
|
bsum -= boutsum;
|
||||||
|
|
||||||
|
stackstart = stackpointer - radius + div;
|
||||||
|
sir = stack[stackstart % div];
|
||||||
|
|
||||||
|
routsum -= sir[0];
|
||||||
|
goutsum -= sir[1];
|
||||||
|
boutsum -= sir[2];
|
||||||
|
|
||||||
|
if (y == 0) {
|
||||||
|
vmin[x] = Math.min(x + radius + 1, wm);
|
||||||
|
}
|
||||||
|
p = pix[yw + vmin[x]];
|
||||||
|
|
||||||
|
sir[0] = (p & 0xff0000) >> 16;
|
||||||
|
sir[1] = (p & 0x00ff00) >> 8;
|
||||||
|
sir[2] = (p & 0x0000ff);
|
||||||
|
|
||||||
|
rinsum += sir[0];
|
||||||
|
ginsum += sir[1];
|
||||||
|
binsum += sir[2];
|
||||||
|
|
||||||
|
rsum += rinsum;
|
||||||
|
gsum += ginsum;
|
||||||
|
bsum += binsum;
|
||||||
|
|
||||||
|
stackpointer = (stackpointer + 1) % div;
|
||||||
|
sir = stack[(stackpointer) % div];
|
||||||
|
|
||||||
|
routsum += sir[0];
|
||||||
|
goutsum += sir[1];
|
||||||
|
boutsum += sir[2];
|
||||||
|
|
||||||
|
rinsum -= sir[0];
|
||||||
|
ginsum -= sir[1];
|
||||||
|
binsum -= sir[2];
|
||||||
|
|
||||||
|
yi++;
|
||||||
|
}
|
||||||
|
yw += w;
|
||||||
|
}
|
||||||
|
for (x = 0; x < w; x++) {
|
||||||
|
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||||
|
yp = -radius * w;
|
||||||
|
for (i = -radius; i <= radius; i++) {
|
||||||
|
yi = Math.max(0, yp) + x;
|
||||||
|
|
||||||
|
sir = stack[i + radius];
|
||||||
|
|
||||||
|
sir[0] = r[yi];
|
||||||
|
sir[1] = g[yi];
|
||||||
|
sir[2] = b[yi];
|
||||||
|
|
||||||
|
rbs = r1 - Math.abs(i);
|
||||||
|
|
||||||
|
rsum += r[yi] * rbs;
|
||||||
|
gsum += g[yi] * rbs;
|
||||||
|
bsum += b[yi] * rbs;
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
rinsum += sir[0];
|
||||||
|
ginsum += sir[1];
|
||||||
|
binsum += sir[2];
|
||||||
|
} else {
|
||||||
|
routsum += sir[0];
|
||||||
|
goutsum += sir[1];
|
||||||
|
boutsum += sir[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < hm) {
|
||||||
|
yp += w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yi = x;
|
||||||
|
stackpointer = radius;
|
||||||
|
for (y = 0; y < h; y++) {
|
||||||
|
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
|
||||||
|
pix[yi] = (0xff000000 & pix[Math.round(yi)]) | (dv[Math.round(rsum)] << 16) | (dv[
|
||||||
|
Math.round(gsum)] << 8) | dv[Math.round(bsum)];
|
||||||
|
|
||||||
|
rsum -= routsum;
|
||||||
|
gsum -= goutsum;
|
||||||
|
bsum -= boutsum;
|
||||||
|
|
||||||
|
stackstart = stackpointer - radius + div;
|
||||||
|
sir = stack[stackstart % div];
|
||||||
|
|
||||||
|
routsum -= sir[0];
|
||||||
|
goutsum -= sir[1];
|
||||||
|
boutsum -= sir[2];
|
||||||
|
|
||||||
|
if (x == 0) {
|
||||||
|
vmin[y] = Math.min(y + r1, hm) * w;
|
||||||
|
}
|
||||||
|
p = x + vmin[y];
|
||||||
|
|
||||||
|
sir[0] = r[p];
|
||||||
|
sir[1] = g[p];
|
||||||
|
sir[2] = b[p];
|
||||||
|
|
||||||
|
rinsum += sir[0];
|
||||||
|
ginsum += sir[1];
|
||||||
|
binsum += sir[2];
|
||||||
|
|
||||||
|
rsum += rinsum;
|
||||||
|
gsum += ginsum;
|
||||||
|
bsum += binsum;
|
||||||
|
|
||||||
|
stackpointer = (stackpointer + 1) % div;
|
||||||
|
sir = stack[stackpointer];
|
||||||
|
|
||||||
|
routsum += sir[0];
|
||||||
|
goutsum += sir[1];
|
||||||
|
boutsum += sir[2];
|
||||||
|
|
||||||
|
rinsum -= sir[0];
|
||||||
|
ginsum -= sir[1];
|
||||||
|
binsum -= sir[2];
|
||||||
|
|
||||||
|
yi += w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let m = 0;m < h; m++) { //y
|
||||||
|
for (let n = 0;n < w; n++) { //x
|
||||||
|
writePromise = new Promise<void>((resolve, reject) => {
|
||||||
|
let buffer1B = new ArrayBuffer(5);
|
||||||
|
let bytes1B = new Uint8Array(buffer1B);
|
||||||
|
var writePositionRenB = {
|
||||||
|
pixels: buffer1B,
|
||||||
|
offset: 1,
|
||||||
|
stride: 1024,
|
||||||
|
region: { size: { width: 1, height: 1 },
|
||||||
|
x: n,
|
||||||
|
y: m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let index = m * w + n;
|
||||||
|
bytes1B[0] = pixEntry[m * w + n].a;
|
||||||
|
bytes1B[1] = ColorUtils.blue(pix[index]);
|
||||||
|
bytes1B[2] = ColorUtils.green(pix[index]);
|
||||||
|
bytes1B[3] = ColorUtils.red(pix[index]);
|
||||||
|
bytes1B[4] = pixEntry[m * w + n].f;
|
||||||
|
bitmap.writePixels(writePositionRenB, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func("success", bitmap);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue