modify animatedimagedrawable,animation bydefault is stopped at creation

This commit is contained in:
houzh 2024-01-18 11:45:25 +08:00
parent 6e47e8a2a6
commit 49d48de586
7 changed files with 142 additions and 54 deletions

View File

@ -28,6 +28,7 @@ AnimatedImageDrawable::AnimatedImageDrawable(cdroid::Context*ctx,const std::stri
LOGD("decoder=%p res=%s",mAnimatedImageState->mDecoder,res.c_str());
ImageDecoder*decoder = ImageDecoder::create(ctx,res);
mAnimatedImageState->mDecoder = decoder;
decoder->load();
#if ENABLE(DMABLIT)
GFXCreateSurface(0,&mImageHandler,decoder->getWidth(),decoder->getHeight(),0,0);
GFXLockSurface(mImageHandler,(void**)&buffer,&pitch);
@ -82,8 +83,8 @@ int AnimatedImageDrawable::getAlpha()const{
}
void AnimatedImageDrawable::draw(Canvas& canvas){
if (!mStarting) {
mStarting = true;
if (mStarting) {
mStarting = false;
postOnAnimationStart();
}
canvas.save();
@ -177,6 +178,7 @@ void AnimatedImageDrawable::postOnAnimationStart(){
callback.onAnimationStart(*this);
}
});
//todo post callback
}
void AnimatedImageDrawable::postOnAnimationEnd(){

View File

@ -7,6 +7,7 @@
#include <cdlog.h>
#include "png.h" /* original (unpatched) libpng is ok */
//REF:https://github.com/xxyyboy/img_apng2webp/blob/main/apng2png/apng2webp.c
//https://gitee.com/mirrors_line/apng-drawable.git
namespace cdroid {
#define APNG_DISPOSE_OP_NONE 0
@ -16,23 +17,112 @@ namespace cdroid {
#define APNG_BLEND_OP_SOURCE 0
#define APNG_BLEND_OP_OVER 1
APNGDecoder::APNGDecoder() {
struct PRIVATE{
png_structp png_ptr;
png_infop info_ptr;
};
APNGDecoder::APNGDecoder(std::unique_ptr<std::istream>stm):ImageDecoder(std::move(stm)) {
mPrivate = new PRIVATE();
}
APNGDecoder::~APNGDecoder() {
}
int APNGDecoder::readImage(Cairo::RefPtr<Cairo::ImageSurface>image,int frameIndex) {
png_uint_16 delay_num , delay_den;
png_byte dispose_op , blend_op;
//ImageFrame* frame = new ImageFrame;
png_structp png_ptr =mPrivate->png_ptr;
png_infop info_ptr=mPrivate->info_ptr;
png_read_frame_head(png_ptr, info_ptr);
uint8_t*frame_pixels;
uint32_t frame_width,frame_height,frame_x,frame_y;
png_get_next_frame_fcTL(png_ptr, info_ptr, &frame_width, &frame_height, &frame_x, &frame_y,
&delay_num, &delay_den, &dispose_op, &blend_op);
//frame->disposalMethod = (dispose_op<<8)|blend_op;
//frame->duration = delay_num * 1000 / (delay_den ? delay_den : 1000);// Convert to milliseconds
frame_pixels = new uint8_t[frame_width * frame_height * 4];
std::vector<png_bytep> row_pointers(frame_height);
/*if(ifrm==0){
memset(frame_pixels,0,frame_width * frame_height * 4);
}else{
switch(snap->disposalMethod>>8){
case APNG_DISPOSE_OP_PREVIOUS:memcpy(frame_pixels,snap->pixels,frame->width*frame->height*4);break;
case APNG_DISPOSE_OP_BACKGROUND:memset(frame_pixels,0,frame->width * frame->height * 4);break;
case APNG_DISPOSE_OP_NONE:break;
}
}*/
for (png_uint_32 y = 0; y < frame_height; ++y) {
row_pointers[y] = frame_pixels + y* frame_width * 4;
}
png_read_image(png_ptr, row_pointers.data());
/*if((dispose_op==APNG_DISPOSE_OP_PREVIOUS)&&((snap->disposalMethod>>8)!=APNG_DISPOSE_OP_PREVIOUS)){
memcpy(snap->pixels,frame->pixels,frame->width * frame->height * 4);
}*/
LOGV("FRAME[%d](%d,%d,%d,%d)op=%d/%d",frameIndex,frame_x,frame_y,frame_width,frame_height,dispose_op,blend_op);
//snap->disposalMethod=(dispose_op<<8)|blend_op;
//mFrames.push_back(frame);
return 0;
}
static void istream_png_reader(png_structp png_ptr, png_bytep png_data, png_size_t data_size){
std::istream* is = (std::istream*)(png_get_io_ptr(png_ptr));
is->read(reinterpret_cast<char*>(png_data), data_size);
};
}
int APNGDecoder::load(std::istream&istream) {
return 0;
int APNGDecoder::load() {
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
std::cerr << "Error creating read struct" << std::endl;
return false;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
std::cerr << "Error creating info struct" << std::endl;
png_destroy_read_struct(&png_ptr, NULL, NULL);
return false;
}
mPrivate->png_ptr = png_ptr;
mPrivate->info_ptr= info_ptr;
if (setjmp(png_jmpbuf(png_ptr))) {
std::cerr << "Error during libpng init_io" << std::endl;
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return false;
}
png_set_read_fn(png_ptr,(void*)istream.get(),istream_png_reader);
png_read_info(png_ptr, info_ptr);
int bit_depth, color_type;
png_get_IHDR(png_ptr, info_ptr,(uint32_t*)&mImageWidth, (uint32_t*)&mImageHeight, &bit_depth, &color_type, NULL, NULL, NULL);
if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr);
}
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
png_set_expand_gray_1_2_4_to_8(png_ptr);
}
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png_ptr);
}
if (bit_depth == 16) {
png_set_strip_16(png_ptr);
}
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_set_gray_to_rgb(png_ptr);
}
png_set_bgr(png_ptr);
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
png_read_update_info(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);
mFrameCount = png_get_num_frames(png_ptr, info_ptr);
return mFrameCount;
}
}/*namesapce*/

View File

@ -7,21 +7,19 @@
namespace cdroid{
typedef struct {
struct PRIVATE{
std::vector<int>delays;
GifFileType*gif;
}GIFPrivate;
GIFDecoder::GIFDecoder(){
GIFPrivate*priv = new GIFPrivate;
priv->gif=nullptr;
mPrivate=priv;
GIFDecoder::GIFDecoder(std::unique_ptr<std::istream>stm):ImageDecoder(std::move(stm)){
mPrivate = new PRIVATE;
mPrivate->gif=nullptr;
}
GIFDecoder::~GIFDecoder(){
GIFPrivate*priv=(GIFPrivate*)mPrivate;
DGifCloseFile((GifFileType*)priv->gif,nullptr);
delete priv;
DGifCloseFile(mPrivate->gif,nullptr);
delete mPrivate;
}
#define ARGB(a, r, g, b) ( ((a) & 0xff) << 24 ) | ( ((r) & 0xff) << 16 ) | ( ((g) & 0xff) << 8 ) | ((b) & 0xff)
@ -36,17 +34,17 @@ static int GIFRead(GifFileType *gifFile, GifByteType *buff, int rdlen){
return is->gcount();
}
static int gifDrawFrame(GifFileType*gif,int&current_frame,size_t pxstride,uint8_t *pixels,bool force_DISPOSE_1);
static int gifDrawFrame(GifFileType*gif,int current_frame,size_t pxstride,uint8_t *pixels,bool force_DISPOSE_1);
int GIFDecoder::load(std::istream&is){
int GIFDecoder::load(){
int err;
GifFileType*gifFileType = DGifOpen(&is,GIFRead,&err);
GifFileType*gifFileType = DGifOpen(istream.get(),GIFRead,&err);
LOGE_IF(gifFileType==nullptr,"git load failed");
if(gifFileType==nullptr)return 0;
DGifSlurp(gifFileType);
mFrameCount = gifFileType->ImageCount;
((GIFPrivate*)mPrivate)->gif = gifFileType;
mPrivate->gif = gifFileType;
mImageWidth = gifFileType->SWidth;
mImageHeight= gifFileType->SHeight;
LOGD("GIF %d frames loaded size(%dx%d)",mFrameCount,mImageWidth,mImageHeight);
@ -54,20 +52,18 @@ int GIFDecoder::load(std::istream&is){
}
int GIFDecoder::readImage(Cairo::RefPtr<Cairo::ImageSurface>image,int frameIndex){
GIFPrivate*priv=(GIFPrivate*)mPrivate;
const int duration=gifDrawFrame(priv->gif,frameIndex,image->get_stride(),image->get_data(),false);
if(priv->delays.size()<frameIndex+1){
priv->delays.push_back(duration);
const int duration = gifDrawFrame(mPrivate->gif,frameIndex,image->get_stride(),image->get_data(),false);
if(frameIndex>=mPrivate->delays.size()){
mPrivate->delays.push_back(duration);
}
return duration;
}
int GIFDecoder::getFrameDuration(int frameIndex)const{
GIFPrivate*priv=(GIFPrivate*)mPrivate;
return priv->delays.at(frameIndex);
return mPrivate->delays.at(frameIndex);
}
static int gifDrawFrame(GifFileType*gif,int&current_frame,size_t pxstride,uint8_t *pixels,bool force_DISPOSE_1) {
static int gifDrawFrame(GifFileType*gif,int current_frame,size_t pxstride,uint8_t *pixels,bool force_DISPOSE_1) {
GifColorType *bg;
GifColorType *color;
SavedImage *frame;

View File

@ -1,6 +1,5 @@
#include <memory>
#include <cstring>
#include <fstream>
#include <drawables/drawable.h>
#include <drawables/bitmapdrawable.h>
#include <drawables/ninepatchdrawable.h>
@ -11,12 +10,13 @@
namespace cdroid{
ImageDecoder::ImageDecoder(){
ImageDecoder::ImageDecoder(std::unique_ptr<std::istream>stm){
mImageWidth = -1;
mImageHeight= -1;
mFrameCount = 0;
mScale = 1.f;
mPrivate = nullptr;
istream = std::move(stm);
}
ImageDecoder::~ImageDecoder(){
@ -97,25 +97,25 @@ ImageDecoder*ImageDecoder::create(Context*ctx,const std::string&resourceId){
constexpr unsigned lengthOfLongestSignature = 14; /* To wit: "RIFF????WEBPVP"*/
char contents[lengthOfLongestSignature];
ImageDecoder*decoder = nullptr;
auto stream = ctx?ctx->getInputStream(resourceId):std::make_unique<std::ifstream>(resourceId,std::ios::in);
stream->read(contents,lengthOfLongestSignature);
unsigned length = stream->gcount();
std::unique_ptr<std::istream>istm = ctx->getInputStream(resourceId);
istm->read(contents,lengthOfLongestSignature);
unsigned length = istm->gcount();
if (length < lengthOfLongestSignature)
return nullptr;
stream->seekg(0,std::ios::beg);
istm->seekg(0,std::ios::beg);
#if ENABLE(GIF)
if (matchesGIFSignature(contents))
decoder = new GIFDecoder();//::create(alphaOption, gammaAndColorProfileOption);
decoder = new GIFDecoder(std::move(istm));
#endif
if (matchesPNGSignature(contents))
decoder = new APNGDecoder();//::create(alphaOption, gammaAndColorProfileOption);
decoder = new APNGDecoder(std::move(istm));
#if USE(ICO)
if (matchesICOSignature(contents) || matchesCURSignature(contents))
return ICOImageDecoder::create(alphaOption, gammaAndColorProfileOption);
#endif
#if ENABLE(JPEG)
if (matchesJPEGSignature(contents))
decoder = new JPEGDecoder();//::create(alphaOption, gammaAndColorProfileOption);
decoder = new JPEGDecoder(std::move(istm));
#endif
#if USE(OPENJPEG)
if (matchesJP2Signature(contents))
@ -127,13 +127,12 @@ ImageDecoder*ImageDecoder::create(Context*ctx,const std::string&resourceId){
#if ENABLE(WEBP)
if (matchesWebPSignature(contents))
return new WebpDecoder();//WEBPImageDecoder::create(alphaOption, gammaAndColorProfileOption);
return new WebpDecoder(std::move(istm));
#endif
#if USE(BITMAP)
if (matchesBMPSignature(contents))
return BMPImageDecoder::create(alphaOption, gammaAndColorProfileOption);
#endif
if(decoder)decoder->load(*stream);
return decoder;
}

View File

@ -10,15 +10,16 @@ namespace cdroid{
class ImageDecoder{
protected:
void*mPrivate;
struct PRIVATE*mPrivate;
int mFrameCount;
int mImageWidth;
int mImageHeight;
float mScale;
std::unique_ptr<std::istream>istream;
public:
ImageDecoder();
ImageDecoder(std::unique_ptr<std::istream>);
virtual ~ImageDecoder();
virtual int load(std::istream&)=0;
virtual int load()=0;
int getWidth()const;
int getHeight()const;
float getScale()const;
@ -32,33 +33,33 @@ public:
class GIFDecoder:public ImageDecoder{
public:
GIFDecoder();
GIFDecoder(std::unique_ptr<std::istream>);
~GIFDecoder()override;
int load(std::istream&)override;
int load()override;
virtual int getFrameDuration(int)const;
int readImage(Cairo::RefPtr<Cairo::ImageSurface>image,int frameIndex)override;
};
class JPEGDecoder:public ImageDecoder{
public:
JPEGDecoder();
int load(std::istream&)override;
JPEGDecoder(std::unique_ptr<std::istream>);
int load()override;
int readImage(Cairo::RefPtr<Cairo::ImageSurface>image,int frameIndex)override;
};
class APNGDecoder:public ImageDecoder{
public:
APNGDecoder();
APNGDecoder(std::unique_ptr<std::istream>);
~APNGDecoder()override;
int load(std::istream&)override;
int load()override;
int readImage(Cairo::RefPtr<Cairo::ImageSurface>image,int frameIndex)override;
};
class WebpDecoder:public ImageDecoder{
public:
WebpDecoder();
WebpDecoder(std::unique_ptr<std::istream>);
~WebpDecoder();
int load(std::istream&)override;
int load()override;
int readImage(Cairo::RefPtr<Cairo::ImageSurface>image,int frameIndex)override;
};
}/*endof namespace*/

View File

@ -8,7 +8,7 @@
namespace cdroid{
JPEGDecoder::JPEGDecoder(){
JPEGDecoder::JPEGDecoder(std::unique_ptr<std::istream>stm):ImageDecoder(std::move(stm)){
}
struct decoder_error_mgr {
@ -156,7 +156,7 @@ int JPEGDecoder::readImage(Cairo::RefPtr<Cairo::ImageSurface>image,int frameInde
return 0;//sfc;
}
int JPEGDecoder::load(std::istream&){
int JPEGDecoder::load(){
return 0;
}
}/*endof namespacee*/

View File

@ -416,15 +416,15 @@ INT GFXBlit(HANDLE dstsurface,int dx,int dy,HANDLE srcsurface,const GFXRect*srcr
opt.stClipRect.u32Width= rs.w;
opt.stClipRect.u32Height=rs.h;
if(nsrc->alpha!=255){
opt.u32GlobalSrcConstColor = 0x00FFFFFF|(0xa0<<24);//(nsrc->alpha<<24);
opt.u32GlobalSrcConstColor = 0x00FFFFFF|(0xa0<<24);//(nsrc->alpha<<24);
opt.u32GlobalDstConstColor = 0xFFFFFFFF;
opt.eSrcDfbBldOp = E_MI_GFX_DFB_BLD_ONE;// 透叠
opt.eDstDfbBldOp = E_MI_GFX_DFB_BLD_INVSRCALPHA;
opt.eDFBBlendFlag = E_MI_GFX_DFB_BLEND_COLORALPHA
| E_MI_GFX_DFB_BLEND_ALPHACHANNEL
opt.eDFBBlendFlag = E_MI_GFX_DFB_BLEND_COLORALPHA
| E_MI_GFX_DFB_BLEND_ALPHACHANNEL
| E_MI_GFX_DFB_BLEND_SRC_PREMULTIPLY;
}else{
opt.u32GlobalSrcConstColor = 0xFFFFFFFF;