svg图片解码改为imageSource解码

Signed-off-by: zenggaofeng <zenggaofeng2@h-partners.com>
This commit is contained in:
zenggaofeng 2023-12-27 11:42:14 +08:00
parent 34a121d454
commit 1cc2202522
14 changed files with 105 additions and 94 deletions

View File

@ -1,3 +1,6 @@
## 2.1.2-rc.3
- svg图片解码改为imageSource解码
-
## 2.1.2-rc.2
- HSP兼容性优化
- 暴露DetachFromLayout接口

View File

@ -80,7 +80,6 @@ struct Index {
加载svg其实和普通流程没有区别,只要将 `loadSrc: $r('app.media.jpgSample'),` `改成一张 loadSrc: $r('app.media.svgSample'),`
svg类型图片即可。
目前加载SVG图片解析依赖了 [SVG三方库](https://gitee.com/openharmony-sig/ohos-svg)由于目前该库还无法解析mask标签所以这里大家需要留意一下。
### 4.加载GIF图片
@ -523,4 +522,44 @@ HSP场景适配:
2.目前svg和gif动图不支持变换效果。
3.svg解析目前不支持mask标签。
## 补充说明
### SVG标签说明
使用版本为(SVG)1.1,当前支持的标签列表有:
- a
- circla
- clipPath
- defs
- ellipse
- feBlend
- feColorMatrix
- feComposite
- feDiffuseLighting
- feDisplacementMap
- feDistantLight
- feFlood
- feGaussianBlur
- feImage
- feMorphology
- feOffset
- fePointLight
- feSpecularLighting
- feSpotLight
- feTurbulence
- filter
- g
- image
- line
- linearGradient
- mask
- path
- pattern
- polygon
- polyline
- radialGradient
- rect
- stop
- svg
- text
- textPath
- tspan
- use

View File

@ -4,7 +4,7 @@
"name": "entry",
"description": "example description",
"repository": {},
"version": "2.1.2-rc.2",
"version": "2.1.2-rc.3",
"dependencies": {
"@ohos/libraryimageknife": "file:../sharedlibrary",
"@ohos/disklrucache": "^2.0.2-rc.0",

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
import {SVGParseImpl} from '@ohos/libraryimageknife'
import {ImageKnifeGlobal} from '@ohos/libraryimageknife'
import { ImageKnifeComponent } from '@ohos/libraryimageknife'
import resourceManager from '@ohos.resourceManager';
import {BusinessError} from '@ohos.base'
import common from '@ohos.app.ability.common';
@ -21,8 +21,8 @@ import common from '@ohos.app.ability.common';
@Component
struct svgTestCasePage {
@State svgSamplePixelMap?:PixelMap = undefined
@State svgIconPixelMap?:PixelMap = undefined
@State svgSamplePixelMap?: Resource = undefined
@State svgIconPixelMap?: Resource = undefined
build() {
Scroll() {
@ -30,20 +30,7 @@ struct svgTestCasePage {
Flex({direction:FlexDirection.Row}){
Button("加载SVG图片")
.onClick(()=>{
((ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext).resourceManager as resourceManager.ResourceManager)
.getMediaContent($r('app.media.svgSample').id)
.then((data:Uint8Array) => {
console.log('basicTestFileIOPage - 本地加载资源 解析后数据data = ' + data)
let svgImpl = new SVGParseImpl();
svgImpl.parseSvg(data.buffer).then((pixelmap)=>{
this.svgSamplePixelMap = pixelmap;
})
})
.catch((err:BusinessError) => {
console.log('basicTestFileIOPage - 本地加载资源err' + JSON.stringify(err));
})
this.svgSamplePixelMap = $r('app.media.svgSample')
}).margin({left:5}).backgroundColor(Color.Blue)
}
@ -51,7 +38,9 @@ struct svgTestCasePage {
Text("下面为展示图片区域").margin({top:5})
Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }){
Image(this.svgSamplePixelMap == undefined ? '':this.svgSamplePixelMap!)
ImageKnifeComponent({imageKnifeOption:{
loadSrc:this.svgSamplePixelMap as Resource
}})
.width(400)
.height(400)
.backgroundColor(Color.Pink)
@ -60,20 +49,7 @@ struct svgTestCasePage {
Flex({direction:FlexDirection.Row}){
Button("加载SVG图片")
.onClick(()=>{
((ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext).resourceManager as resourceManager.ResourceManager)
.getMediaContent($r('app.media.iconsvg').id)
.then(data => {
console.log('basicTestFileIOPage - 本地加载资源 解析后数据data = ' + data)
let svgImpl = new SVGParseImpl();
svgImpl.parseSvg(data.buffer).then((pixelmap)=>{
this.svgIconPixelMap = pixelmap;
})
})
.catch((err:BusinessError) => {
console.log('basicTestFileIOPage - 本地加载资源err' + JSON.stringify(err));
})
this.svgIconPixelMap = $r('app.media.iconsvg')
}).margin({left:5}).backgroundColor(Color.Blue)
}
@ -81,7 +57,9 @@ struct svgTestCasePage {
Text("下面为展示图片区域").margin({top:5})
Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }){
Image(this.svgIconPixelMap == undefined ? '':this.svgIconPixelMap!)
ImageKnifeComponent({imageKnifeOption:{
loadSrc:this.svgIconPixelMap as Resource
}})
.width(400)
.height(400)
.backgroundColor(Color.Pink)

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="ic_launcher_round.css" ?>
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 800 800" xml:space="preserve">
viewBox="0 0 800 800" xml:space="preserve" width="200" height="200">
<rect class="brick4" width="800" height="800.5" fill="#6A6ACC"/>
<g fill="#55346A">
<path d="M242.4,800.6c-0.2-0.9-0.3-1.9-0.5-2.8c-0.2-0.8-0.3-1.7-0.5-2.5c-0.5-2.5-1.1-5-1.7-7.5l0,0

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -14,11 +14,10 @@
"main": "index.ets",
"repository": "https://gitee.com/openharmony-tpc/ImageKnife",
"type": "module",
"version": "2.1.2-rc.2",
"version": "2.1.2-rc.3",
"dependencies": {
"pako": "^2.1.0",
"@ohos/disklrucache": "^2.0.2-rc.0",
"@ohos/svg": "^2.1.1-rc.0",
"@ohos/gpu_transform": "^1.0.0"
},
"tags": [

View File

@ -15,7 +15,6 @@
import { GIFFrame } from './utils/gif/GIFFrame'
import { DetachFromLayout } from './RequestOption'
import { LogUtil } from './utils/LogUtil'
import { Ellipse2 } from '@ohos/svg/src/main/ets/components/utils/SVGBase'
export enum ImageKnifeType {
PIXELMAP = 'PixelMap',

View File

@ -91,13 +91,7 @@ export class ErrorHolderManager<T> {
private svgProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
let svgParseImpl:SVGParseImpl = new SVGParseImpl()
let size:Size = { width: this.options.size.width, height: this.options.size.height }
svgParseImpl.parseSvg(arraybuffer, size).then((value: PixelMap) => {
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
onComplete(imageKnifeData)
}).catch((err:BusinessError) => {
onError(err)
})
svgParseImpl.parseSvg(this.options,arraybuffer, onComplete,onError);
}
private mediaImageProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {

View File

@ -89,13 +89,7 @@ export class PlaceHolderManager<T> {
private svgProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
let svgParseImpl:SVGParseImpl = new SVGParseImpl()
let size:Size = { width: this.options.size.width, height: this.options.size.height }
svgParseImpl.parseSvg(arraybuffer, size).then((value: PixelMap) => {
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
onComplete(imageKnifeData)
}).catch((err:BusinessError) => {
onError(err)
})
svgParseImpl.parseSvg(this.options,arraybuffer, onComplete,onError);
}
private mediaImageProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {

View File

@ -89,13 +89,7 @@ export class RetryHolderManager<T> {
private svgProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
let svgParseImpl = new SVGParseImpl()
let size:Size = { width: this.options.size.width, height: this.options.size.height }
svgParseImpl.parseSvg(arraybuffer, size).then((value: PixelMap) => {
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
onComplete(imageKnifeData)
}).catch( (err:BusinessError) => {
onError(err)
})
svgParseImpl.parseSvg(this.options,arraybuffer, onComplete,onError);
}
private mediaImageProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {

View File

@ -189,7 +189,7 @@ export class RequestManager {
// 加载网络资源
private loadSourceFromNetwork(request: RequestOption, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
let success = (arraybuffer:ArrayBuffer) => {
this.downloadSuccess(arraybuffer, onComplete, onError)
this.downloadSuccess(request,arraybuffer, onComplete, onError)
}
let error = (errorMsg:string) =>{
onError(errorMsg)
@ -214,7 +214,7 @@ export class RequestManager {
})
}else if(ImageKnifeData.SVG == typeValue){
// 处理svg
this.svgProcess(onComplete,onError,arrayBuffer,typeValue,(imageKnifeData)=>{
this.svgProcess(request,onComplete,onError,arrayBuffer,typeValue,(imageKnifeData)=>{
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey,imageKnifeData)
})
} else {
@ -318,7 +318,7 @@ export class RequestManager {
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
})
}else if(ImageKnifeData.SVG == typeValue){
this.svgProcess(onComplete,onError, source, typeValue, (imageKnifeData)=>{
this.svgProcess(request,onComplete,onError, source, typeValue, (imageKnifeData)=>{
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
})
} else {
@ -433,7 +433,7 @@ export class RequestManager {
}
}
private downloadSuccess(source: ArrayBuffer, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
private downloadSuccess(request: RequestOption,source: ArrayBuffer, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
LogUtil.log('Download task completed.');
if(source == null || source == undefined || source.byteLength <= 0){
@ -474,7 +474,7 @@ export class RequestManager {
})
}else if(ImageKnifeData.SVG == filetype){
// 处理svg
this.svgProcess(onComplete,onError, source, filetype, (imageKnifeData)=>{
this.svgProcess(request,onComplete,onError, source, filetype, (imageKnifeData)=>{
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
})
@ -596,18 +596,9 @@ export class RequestManager {
}})
}, this.options.thumbDelayTime)
}
private svgProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string, cacheStrategy?: (cacheData: ImageKnifeData) => void) {
private svgProcess(option: RequestOption,onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string, cacheStrategy?: (cacheData: ImageKnifeData) => void) {
let svgParseImpl = new SVGParseImpl()
let size:Size = { width: this.options.size.width, height: this.options.size.height }
svgParseImpl.parseSvg(arraybuffer, size).then((value: PixelMap) => {
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
if(cacheStrategy){
cacheStrategy(imageKnifeData)
}
onComplete(imageKnifeData)
}).catch((err:BusinessError) => {
onError(err)
})
svgParseImpl.parseSvg(option,arraybuffer, onComplete,onError)
}
private gifProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string, cacheStrategy?: (cacheData: ImageKnifeData) => void) {

View File

@ -12,8 +12,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Size} from '../../RequestOption'
import { RequestOption } from '../../RequestOption'
import { BusinessError } from '@ohos.base'
import { ImageKnifeData } from '../../ImageKnifeData'
export interface IParseSvg {
// 解析svg
parseSvg:(imageinfo: ArrayBuffer,size?:Size)=> Promise<PixelMap>
parseSvg:(option: RequestOption, imageInfo: ArrayBuffer | ArrayBufferLike,
onComplete: (value: ImageKnifeData) => void | PromiseLike<ImageKnifeData>,
onErrorFunction: (reason?: BusinessError | string) => void)=> void
}

View File

@ -12,20 +12,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {IParseSvg} from'./IParseSvg'
import {SVGImageView} from '@ohos/svg'
import {Size} from '../../RequestOption'
import { IParseSvg } from './IParseSvg'
import { RequestOption } from '../../RequestOption'
import { BusinessError } from '@ohos.base'
import { ImageKnifeData, ImageKnifeType } from '../../ImageKnifeData'
import image from '@ohos.multimedia.image'
export class SVGParseImpl implements IParseSvg{
parseSvg(imageinfo: ArrayBuffer | ArrayBufferLike,size?:Size): Promise<PixelMap>{
let model = new SVGImageView.SVGImageViewModel();
let svgSize:SVGImageView.Size = new SVGImageView.Size();
svgSize.width = 0;
svgSize.height = 0;
if(size != undefined){
svgSize.width = size.width;
svgSize.height = size.height;
}
return model.getSVGPixelMap(new Uint8Array(imageinfo),svgSize);
export class SVGParseImpl implements IParseSvg {
parseSvg(option: RequestOption, imageInfo: ArrayBuffer,
onComplete: (value: ImageKnifeData) => void | PromiseLike<ImageKnifeData>,
onErrorFunction: (reason?: BusinessError | string) => void) {
let imageSource: image.ImageSource = image.createImageSource(imageInfo); // 步骤一文件转为pixelMap 然后变换 给Image组件
let hValue = Math.round(option.size.height);
let wValue = Math.round(option.size.width);
let defaultSize: image.Size = {
height: hValue,
width: wValue
};
let opts: image.DecodingOptions = {
editable: true,
desiredSize: defaultSize
};
imageSource.createPixelMap(opts).then((pixelMap: image.PixelMap) => {
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, pixelMap)
onComplete(imageKnifeData);
imageSource.release()
}).catch((err: string) => {
onErrorFunction(err);
imageSource.release()
})
}
}

View File

@ -6,6 +6,6 @@
"name": "imageknife",
"description": "example description",
"repository": {},
"version": "2.1.2-rc.2",
"version": "2.1.2-rc.3",
"dependencies": {}
}