這些PAG常用方法解讀也能幫助大家使用起來更輕松:
PAG 運行時編輯
PAG 的運行時編輯主要分為兩類:1)修改文本圖層的文本信息、替換圖片圖層中的占位圖、修改實色圖層中的顏色
//C++std::shared_ptrReplaceImageOrText() {autopagFile=pag::PAGFile::Load("../../assets/test2.pag");if(pagFile==nullptr){returnnullptr;}for(inti=0;inumImages();i++){autopagImage=pag::PAGImage::FromPath("../../assets/scene.png");pagFile->replaceImage(i,pagImage);}for(inti=0;inumTexts();i++){autotextDocumentHandle=pagFile->getTextData(i);textDocumentHandle->text="hah哈哈哈哈哈";pagFile->replaceText(i,textDocumentHandle);}returnpagFile;}
2)渲染樹編輯
(資料圖片僅供參考)
渲染樹編輯指的是通過使用 PAGComposition 的相關接口,完成多個圖層、多個 pag 文件的自由組合。具體如何使用可以參考下面的代碼:
//以OC版本為例-(PAGComposition*)makeComposition{PAGComposition*compostion=[PAGCompositionMake:self.view.bounds.size];floatitemWidth=self.view.bounds.size.width/5;floatitemHeight=100;for(inti=0;i<20;i++){PAGFile*pagFile=[selfgetPAGFile:i/5clume:i%5name:[NSStringstringWithFormat:@"%d",i]itemWidth:itemWidthitemHeight:itemHeight];[compostionaddLayer:pagFile];}returncompostion;}-(PAGFile*)getPAGFile:(int)rowclume:(int)columename:(NSString*)nameitemWidth:(float)itemWidthitemHeight:(float)itemHeight{PAGFile*pagFile=[PAGFileLoad:[[NSBundlemainBundle]pathForResource:nameofType:@"pag"]];if(pagFile){floatscaleX=itemWidth*1.0f/[pagFilewidth];CGAffineTransformtransform=CGAffineTransformMakeScale(scaleX,scaleX);CGAffineTransformtranflate=CGAffineTransformMakeTranslation(itemWidth*colume,row*itemHeight+150);transform=CGAffineTransformConcat(transform,tranflate);[pagFilesetMatrix:transform];[pagFilesetStartTime:0];[pagFilesetDuration:10000000];}returnpagFile;}
PAG UI場景及列表播放
當一個頁面中含有多個pag 文件時,如果使用多個 PAGView,由于每一個 PAGView 都需要一個獨立的渲染環境,內存和 CPU 占用相對較高,推薦的處理方法有兩種:
1)通過使用 PAG 的組合模式用將多個 PAG 文件添加到同一個 PAGComposition 中,具體使用方法見運行時編輯,從而將多個渲染環境縮減到一個渲染環境,降低內存和 CPU 占用;
2)對于一些 UI 列表場景,需要有多個 View 的存在, pag 文件無法添加到一個 PAGComposition 中,此時可以使用 PAGImageView。
//以OC版本為例#import#defineWIDTH100@interfacePAGCell:UITableViewCell@property(nonatomic,strong)PAGImageView*pagImageView;@property(nonatomic,strong)NSString*filePath;@end@implementationPAGCell-(instancetype)initWithStyle:(UITableViewCellStyle)stylereuseIdentifier:(NSString*)reuseIdentifier{if(self=[superinitWithStyle:stylereuseIdentifier:reuseIdentifier]){self.pagImageView=[[PAGImageViewalloc]initWithFrame:CGRectMake(20,0,WIDTH,WIDTH)];[self.contentViewaddSubview:self.pagImageView];}returnself;}-(void)setFilePath:(NSString*)filePath{if([filePathlength]>0){[self.pagImageViewsetPath:filePath];[self.pagImageViewsetCurrentFrame:0];[self.pagImageViewsetRepeatCount:-1];[self.pagImageViewplay];}}
PAG 字體注冊
PAG 除了支持修改文本圖層的文本信息外,還支持修改字體。具體方法如下:
(1)通過 PAGFont 獲取字體的相關信息,然后賦值給 PAGText,使用到的接口如下:
獲取字體信息
//C++/***Registersafontrequiredbythetextlayersinpagfiles,sothattheycanberenderedas*designed.*/staticPAGFontRegisterFont(conststd::string&fontPath,intttcIndex,conststd::string&fontFamily="",conststd::string&fontStyle="");/***Registersafontrequiredbythetextlayersinpagfiles,sothattheycanberenderedas*designed.*/staticPAGFontRegisterFont(constvoid*data,size_tlength,intttcIndex,conststd::string&fontFamily="",conststd::string&fontStyle="");PAGFont(std::stringfontFamily,std::stringfontStyle):fontFamily(std::move(fontFamily)),fontStyle(std::move(fontStyle)){}/***Astringwiththenameofthefontfamily.**/conststd::stringfontFamily;/***Astringwiththestyleinformation—e.g.,“bold”,“italic”.**/conststd::stringfontStyle;
(2)fontFamlily 和 fontStyle 賦值給 PAGText,PAGText 再填充到 PAGTextLayer 中。
//C++for(inti=0;inumTexts();i++){autotextDocumentHandle=pagFile->getTextData(i);textDocumentHandle->text="hah哈哈哈哈哈";//UsespecialfontautopagFont=pag::PAGFont::RegisterFont("../../resources/font/NotoSansSC-Regular.otf",0);textDocumentHandle->fontFamily=pagFont.fontFamily;textDocumentHandle->fontStyle=pagFont.fontStyle;pagFile->replaceText(i,textDocumentHandle);}
如果使用了特定字體而又沒有注冊或字體文件中沒有包含該字符,PAG 內部(Android、iOS、macOS、Windows 平臺)有一個默認字體列表(同時支持外部設置字體回退列表,外部設置時會覆蓋默認設置),會回退到 PAG 的默認字體列表中,此時使用那種字體對于業務方而言是不確定的。
//C++/***Resetsthefallbackfontnames.Itshouldbecalledonlyoncewhentheapplicationisbeing*initialized.*/staticvoidSetFallbackFontNames(conststd::vector&fontNames);/***Resetsthefallbackfontpaths.Itshouldbecalledonlyoncewhentheapplicationisbeing*initialized.*/staticvoidSetFallbackFontPaths(conststd::vector&fontPaths,conststd::vector&ttcIndices);
PAG 視頻編輯場景
在視頻編輯場景,使用的不是 PAGView,而是 PAGPlayer、PAGSurface 和 PAGComposition。
PAGSurface 可以通過 CVPixelBufferRef 或紋理創建,方便快捷的與視頻后編輯中的 CVPixelBuffer 或 紋理進行整合。同時 PAGImage 也支持通過 CVPixelBufferRef 或 紋理創建,通過 PAGPlayer 控制播放進度,將視頻內容填充進圖片圖層的占位圖。
//OC/***CreatesaPAGImageobjectfromthespecifiedCVPixelBuffer,returnnulliftheCVPixelBufferis*invalid.*/+(PAGImage*)FromPixelBuffer:(CVPixelBufferRef)pixelBuffer;//javapublicstaticPAGImageFromTexture(inttextureID,inttextureTarget,intwidth,intheight);publicstaticPAGImageFromTexture(inttextureID,inttextureTarget,intwidth,intheight,booleanflipY);
PAG 軟解注入
為什么會有軟解注入?PAG 的導出方式中支持 BMP 預合成導出,在 pag 文件中,如果含有 BMP 預合成,一個 BMP 預合成相當于一個視頻,視頻則需要解碼。在 PAG SDK 中默認使用硬件解碼,但硬件解碼存在兩個問題:
1)移動端硬件解碼器的瞬時存在數目是有限制的,不能無限的創建,如果創建硬件解碼器的數目超過限制,就會出現解碼器創建失敗的情況,在視頻編輯場景中需要關注;
2)Android 平臺由于機型兼容性、碎片化驗證,不能保證所有的機型都能硬件解碼成功,因此 Android 平臺軟解是必須的。
于是,在提供的制品庫中, iOS 平臺由于沒有兼容性的問題,默認是不帶軟解的,Android 提供了兩個包,普通的包默認是內置軟解的,noffavc 的包是沒有內置軟解的。
具體怎么注入軟解呢:Android 平臺可以選擇完整制品庫,iOS 平臺可以引入 ffavc。
pod"ffavc"
通過如下方法完成軟件解碼器的注冊:
//OC-(void)registerSoftwareDecoder{//注冊軟件解碼器工廠指針autofactory=ffavc::DecoderFactory::GetHandle();[PAGVideoDecoderRegisterSoftwareDecoderFactory:(void*)factory];}
如果接入方自己的 APP 中已經內置了軟解庫,可以通過外部注入的方式注入軟解。
PAG 官網提供了下面這個軟解注入接口,需要業務方基于自己的解碼器實現,PAG BMP 預合成中的視頻編碼格式為 h264。
https://github.com/libpag/ffavc/blob/main/vendor/libpag/include/pag/decoder.h
具體的實現方式可以參考:
ffavc/FFAVCDecoder.cpp at main · libpag/ffavc · GitHub
然后自己通過上面提到的方式注入軟解。
PAG 服務端渲染
和 Lottie、SVGA 不同的是,PAG 支持服務端渲染,盡管 PAG 的渲染依賴 OpenGL 環境,但 服務端卻可以繼續使用 CPU 服務器。具體實現層面,PAG 通過 swiftshader 在 CPU 服務器上構建出了 OpenGL 環境,使得 pag 文件可以在 CPU 環境中正常渲染。
在服務端的具體使用如下,獲取到的是 BGRA 的數據,該數據可以用于視頻編碼。
//C++autopagFile=pag::PAGFile::Load("../../assets/test2.pag");autopagSurface=pag::PAGSurface::MakeOffscreen(pagFile->width(),pagFile->height());if(pagSurface==nullptr){printf("---pagSurfaceisnullptr!!!\n");return-1;}autopagPlayer=newpag::PAGPlayer();pagPlayer->setSurface(pagSurface);pagPlayer->setComposition(pagFile);autototalFrames=TimeToFrame(pagFile->duration(),pagFile->frameRate());autocurrentFrame=0;intbytesLength=pagFile->width()*pagFile->height()*4;while(currentFrame<=totalFrames){pagPlayer->setProgress(currentFrame*1.0/totalFrames);autostatus=pagPlayer->flush();//PAG渲染數據讀取autodata=newuint8_t[bytesLength];pagSurface->readPixels(pag::ColorType::BGRA_8888,pag::AlphaType::Premultiplied,data,pagFile->width()*4);delete[]data;currentFrame++;}deletepagPlayer;
開始使用 :如何接入
接入使用分為開發部分和設計部分,這里分別為大家介紹下:
(1) 開發者——接入SDK
在PAG的Github Wiki中有非常詳細的接入指引(包括Android、iOS、Web等平臺的接入方法和范例工程),大家自行學習就好:https://github.com/Tencent/libpag/wiki
(2)設計師——下載導出插件和預覽工具
設計師想要使用PAG,只需在官網下載預覽工具 PAGViewer和 AE 導出插件即可:https://pag.art/docs/install.html
整體看來,PAG的核心價值如下:
據官網顯示已經有很多頭部應用接入使用(如微信、王者榮耀、小紅書、知乎等),穩定性應該很有保證,如果有動效上線相關業務的朋友非常值得試試。
最后順便附上 PAG 相關的資源,大家感興趣可以進一步了解:
官網: https:/pag.art/
Github:https://github.com/Tencent/libpag
QQ 群:893379574

- 開曼群島屬于哪個洲?開曼群島是一個國家嗎?開曼群島屬于北美洲。開曼群島是英國在美洲西加勒比群島的一...
- 狼的精神是什么?《狼道》金句有哪些?狼的精神經典十六字是如下:一、發憤圖強:狼不會為了莊嚴,...
- 世界上最大的內陸國?世界上最小的內陸國?所謂的內陸國,又稱陸鎖國,指的是沒有海岸線的國家,亦即被...
- 大貝爾橋是哪個國家的?布魯塞爾是哪個國家的城市?1、大貝爾特橋位于丹麥;2、大貝爾特橋是一座連接丹麥西蘭島和...
- 我國第一艘航母是用什么省的名稱命名的?我國第一艘蒸汽機輪船是什么號?我國第一艘航母是用遼寧省的名稱命名的。為遼寧艦,舷號16,...
- 信托產品收益率是多少?信托為什么收益那么高?
2023-04-13 14:35:27
- 什么是股票發行市場?發行市場和交易市場的區別?
2023-04-10 14:53:09
- 深市新股首日漲停規則?新股的漲幅為何是44%?
2023-03-20 14:21:02
- 北向資金從哪里看?北向資金看什么指標?
2023-03-10 11:12:33
- 場內基金和場外基金的區別?散戶買ETF最大的優點?
2023-03-06 16:55:46