Files
player/Project/Src/MyWinApp/mywin_user_photo.c

573 lines
12 KiB
C
Raw Permalink Normal View History

2025-06-27 00:32:57 +08:00
#include "mywin_inc.h"
#include "mywin_user_photo.h"
#include "ff.h"
#include "picdeco.h"
#include "bmp.h"
#include "png.h"
#include <zlib.h>
#include "system_file.h"
#define WIN_PHOTO_TYPE "WIN_PhotoStruct"
static const char *g_popup_itmes[]=
{
"设置为背景",
"转换为灰度",
"转换为位图",
"退出",
};
WIN_PhotoStruct *WIN_CreatPhoto (WIN_WindowStruct *base,
void (*msgLoop)(struct _WIN_WindowStruct *win,WIN_MsgStruct *msg),
int x,int y,int x_size,int y_size)
{
//重设消息循环
if (msgLoop==0)
{
msgLoop=(void (*)(struct _WIN_WindowStruct *win,WIN_MsgStruct *msg))PHOTO_defaultMsgLoop;
}
WIN_PhotoStruct *ret=mymalloc (sizeof ( WIN_PhotoStruct));
//调用父类的构造函数
if (ret)
{
mymemset (ret,0,sizeof ( WIN_PhotoStruct));
if (0==WIN_CreatWindowExt((WIN_WindowStruct *)ret,base,msgLoop,x,y,x_size,y_size))
{
//创建失败
myfree (ret);
ret=0;
}
else
{
//构造
((WIN_WindowStruct *)ret)->deleteWindow=(void (*)(struct _WIN_WindowStruct *win))WIN_DeletePhoto;
((WIN_WindowStruct *)ret)->winType=WIN_PHOTO_TYPE;
((WIN_WindowStruct *)ret)->intercept=1;
((WIN_WindowStruct *)ret)->bkcolor=0x808080;
((WIN_WindowStruct *)ret)->color=0xffffff;
}
}
return ret;
}
void WIN_DeletePhoto (WIN_PhotoStruct *photo)
{
if (photo->memData)
{
myfree (photo->memData);
}
if (photo->memDataGray)
{
myfree (photo->memDataGray);
}
if (photo->memDataBit)
{
myfree (photo->memDataBit);
}
//调用父类的销毁函数
WIN_DeleteWindow ( (WIN_WindowStruct *)photo);
}
//设置图片
void PHOTO_SetPic (WIN_PhotoStruct *photo,WIN_PicStruct *pic)
{
mymemcpy(&((WIN_WindowStruct *)photo)->pic,pic,sizeof(WIN_PicStruct));
mymemcpy(&photo->pic,pic,sizeof(WIN_PicStruct));
}
static int go_trsGray (void *ptr)
{
WIN_PhotoStruct *photo =ptr;
u16 *img=photo->memDataGray;
for (int i=0;i<photo->pic.xsize*photo->pic.ysize;i++)
{
img[i]=RGB2GRAY (photo->pic.data[i]);
img[i]=GRAY2RGB (img[i]);
}
photo->grayTrs=1;
return 0;
}
//转化为灰度图
void PHOTO_TransforGray (WIN_PhotoStruct *photo)
{
if (photo->memDataGray==0)
{
photo->memDataGray=mymalloc (photo->pic.xsize*photo->pic.ysize*2);
}
if ((photo->memDataGray)&&(photo->grayTrs==0))
{
WORKING_DoWork ((WIN_WindowStruct *)photo,"正在生成灰度图。。。",go_trsGray,photo);
}
if (photo->grayTrs)
{
if (photo->pic.data!=photo->memDataGray)
photo->pic.data=photo->memDataGray;
else photo->pic.data=photo->memData;
}
}
static u16 getBit (WIN_PicStruct *pic,int x,int y)
{
if ((x<0||x>=pic->xsize)||(y<0||y>=pic->ysize))
return 0;
else
return pic->data[y*pic->xsize+x]&0x1f;
}
static u16 setBit (WIN_PicStruct *pic,int x,int y,int color)
{
if ((x<0||x>=pic->xsize)||(y<0||y>=pic->ysize))
return 0;
else
{
if (color>0x1f)
return pic->data[y*pic->xsize+x]=0x1f;
else if (color<0)
return pic->data[y*pic->xsize+x]=0;
else
return pic->data[y*pic->xsize+x]=color;
}
}
static u16 getBitRand (WIN_PicStruct *pic,int lev,int x,int y)
{
if ((getBit(pic,x,y)&0x1f)>lev)
return 0x1f;
else
return 0;
}
static int do_work (void *ptr)
{
WIN_PhotoStruct *photo=ptr;
if (photo->memDataBit)
{
u16 *ptr=photo->memDataBit;
u16 *src=photo->memDataGray;
long lev=0;
for (int i=0;i<photo->pic.xsize*photo->pic.ysize;i++)
{
ptr[i]=0x1f&src[i];
lev+=ptr[i];
}
lev/=photo->pic.xsize*photo->pic.ysize;
photo->pic.data=ptr;
for (int y=0;y<photo->pic.ysize;y++)
{
for (int x=0;x<photo->pic.xsize;x++)
{
u16 color_old=ptr[y*photo->pic.xsize+x];
ptr[y*photo->pic.xsize+x]=getBitRand(&photo->pic,lev,x,y);
int quant_error=color_old-ptr[y*photo->pic.xsize+x];
setBit (&photo->pic,x+1,y, getBit(&photo->pic,x+1,y)+quant_error *7/16);
setBit (&photo->pic,x-1,y+1, getBit(&photo->pic,x-1,y+1)+quant_error *3/16);
setBit (&photo->pic,x,y+1, getBit(&photo->pic,x,y+1)+quant_error *5/16);
setBit (&photo->pic,x+1,y+1, getBit(&photo->pic,x+1,y+1)+quant_error *1/16);
if (ptr[y*photo->pic.xsize+x]) ptr[y*photo->pic.xsize+x]=0xffff;
}
}
photo->pic.data=photo->memData;
photo->bitTrs=1;
}
return 0;
}
//转化为位图
int PHOTO_TransforBit (WIN_PhotoStruct *photo)
{
if (photo->grayTrs)
{
if (photo->memDataBit==0)
{
photo->memDataBit=mymalloc (photo->pic.xsize*photo->pic.ysize*2);
WORKING_DoWork ((WIN_WindowStruct *)photo,"正在生成位图。。。",do_work,photo);
}
}
if (photo->bitTrs)
{
if (photo->pic.data!=photo->memDataBit)
photo->pic.data=photo->memDataBit;
else photo->pic.data=photo->memData;
}
return 0;
}
//消息框的绘制函数
void PHOTO_DefaultPaint (WIN_PhotoStruct *photo)
{
WIN_WindowStruct *win=(WIN_WindowStruct *)photo;
WIN_PicStruct *pic=&win->pic;
int xsize=win->x_size;
int ysize=win->y_size;
if(pic->format==PIC_FORMAT_RGB565)
WIN_FillRect (0,0,xsize,ysize,pic->data,0,0,pic->xsize,pic->ysize);
else if(pic->format==PIC_FORMAT_ARGB8888)
WIN_FillRectAlpha (0,0,xsize,ysize,pic->data,0,0,pic->xsize,pic->ysize);
}
static void PHOTO_Enter (WIN_PhotoStruct *photo,int x,int y)
{
int index=POPUP_SelectItem ((WIN_WindowStruct *)photo,(char **)g_popup_itmes,4,x,y);
if (index==0)
{
//设置为背景
WIN_PicStruct pic={0};
WIN_PicStruct *win_pic=&((WIN_WindowStruct *)photo)->pic;
WIN_WindowStruct *home=WIN_GetWinByTitle(0,"home");
if(home)
{
pic.data=home->pic.data;
pic.xsize=home->pic.xsize;
pic.ysize=home->pic.ysize;
int xsize=pic.xsize;int ysize=pic.ysize;
if (xsize>win_pic->xsize) xsize=win_pic->xsize;
if (ysize>win_pic->ysize) ysize=win_pic->ysize;
for (int i=0;i<ysize;i++)
{
for (int j=0;j<xsize;j++)
{
pic.data[i*pic.xsize+j]=win_pic->data[i*win_pic->xsize+j];
}
}
}
}
else if (index==1)
{
//转换为灰度图
PHOTO_TransforGray (photo);
((WIN_WindowStruct *)photo)->pic.data=photo->pic.data+photo->x_off+photo->y_off*photo->pic.xsize;
((WIN_WindowStruct *)photo)->pic.ysize=photo->pic.ysize-photo->y_off;
WIN_SetInvalid ((WIN_WindowStruct *)photo);
}
else if (index==2)
{
//转换为位图
PHOTO_TransforBit (photo);
((WIN_WindowStruct *)photo)->pic.data=photo->pic.data+photo->x_off+photo->y_off*photo->pic.xsize;
((WIN_WindowStruct *)photo)->pic.ysize=photo->pic.ysize-photo->y_off;
WIN_SetInvalid ((WIN_WindowStruct *)photo);
}
else if (index==3)
{
//退出
((WIN_WindowStruct *)photo)->deleteWindow((WIN_WindowStruct *)photo);
}
}
//消息框的消息处理函数
void PHOTO_defaultMsgLoop (WIN_PhotoStruct *photo,WIN_MsgStruct *msg)
{
WIN_MoveStruct *m=0;
WIN_KeyStruct *k=0;
switch (msg->msg)
{
case WIN_MSG_PAINT:
PHOTO_DefaultPaint(photo);
break;
case WIN_MSG_KEY:
k=msg->data.p;
if (k->shortPress&KEY_VALUE_HOME)
((WIN_WindowStruct *)photo)->deleteWindow((WIN_WindowStruct *)photo);
else if (k->shortPress&KEY_VALUE_ENTER)
{
PHOTO_Enter(photo,100,100);
}
break;
case WIN_MSG_MOVE:
m=msg->data.p;
switch (m->moveType)
{
case MOVE_DATA_MOVED:
//等待上次的显示刷新
//while (LCD_GetLayerUpdataStat()==0){}
photo->x_off-=m->x_move;
photo->y_off-=m->y_move;
if (photo->x_off<0) photo->x_off=0;
if (photo->y_off<0) photo->y_off=0;
if (photo->pic.xsize>((WIN_WindowStruct *)photo)->x_size)
{
if (photo->x_off>photo->pic.xsize-((WIN_WindowStruct *)photo)->x_size)
photo->x_off=photo->pic.xsize-((WIN_WindowStruct *)photo)->x_size;
}
else photo->x_off=0;
if (photo->pic.ysize>((WIN_WindowStruct *)photo)->y_size)
{
if (photo->y_off>photo->pic.ysize-((WIN_WindowStruct *)photo)->y_size)
photo->y_off=photo->pic.ysize-((WIN_WindowStruct *)photo)->y_size;
}
else photo->y_off=0;
((WIN_WindowStruct *)photo)->pic.data=photo->pic.data+photo->x_off+photo->y_off*photo->pic.xsize;
((WIN_WindowStruct *)photo)->pic.ysize=photo->pic.ysize-photo->y_off;
WIN_SetInvalid ((WIN_WindowStruct *)photo);
break;
case MOVE_DATA_LONG:
PHOTO_Enter(photo,m->x_move,m->y_move);
break;
default:
WIN_DefaultMsgLoop((WIN_WindowStruct *)photo,msg);
break;
}
break;
default:
WIN_DefaultMsgLoop((WIN_WindowStruct *)photo,msg);
break;
}
}
typedef struct
{
u8 *name;
BITMAP_Struct *bitmap;
}decode_jpg_struct;
//图片解码工作函数
static int decode_jpg ( void *ptr)
{
decode_jpg_struct *p=ptr;
return JPEG_Decode (p->name,p->bitmap);
}
typedef struct
{
u8 *name;
BMP_DecodeStruct *bmp;
}decode_bmp_struct;
static int decode_bmp (void *ptr)
{
decode_bmp_struct *p=ptr;
return BMP_Decode (p->name,p->bmp);
}
typedef struct
{
char *name;
WIN_PicStruct *pic;
}decode_png_struct;
//解码png图片成功返回1失败返回0
static int decode_png(void *ptr)
{
decode_png_struct *p=ptr;
WIN_PicStruct *pic=p->pic;
char *name=p->name;
int png_err=0;
png_image image; /* The control structure used by libpng */
/* Initialize the 'png_image' structure. */
memset(&image, 0, (sizeof image));
image.version = PNG_IMAGE_VERSION;
/* The first argument is the file to read: */
if (png_image_begin_read_from_file(&image, name) != 0)
{
image.format = PNG_FORMAT_BGRA;
pic->data = mymalloc(PNG_IMAGE_SIZE(image));
pic->format=PIC_FORMAT_ARGB8888;
pic->xsize=image.width;
pic->ysize=image.height;
if (
png_err=png_image_finish_read(&image, NULL/*background*/, pic->data,
0/*row_stride*/, NULL/*colormap*/),png_err != 0)
{
return 1;
}
else
{
myfree(pic->data);
return 0;
}
}
return 0;
}
//显示照片
int PHOTO_ShowPhoto (WIN_WindowStruct *base,char *name)
{
//解码图片
BITMAP_Struct bitmap={0};
WIN_PicStruct pic={0};
u8 ret=0;
//判断图片格式
int str_len=strlen(name);
char *p_str=&name[str_len-4];
//解码时显示提示,这个函数是阻塞的
if (strcmp (p_str,".jpg")==0)
{
decode_jpg_struct dec={0};
dec.bitmap=&bitmap;dec.name=(u8*)name;
ret=WORKING_DoWork (base,"JPG解码中。。。",decode_jpg,&dec);
if (ret==0)
{
pic.data=bitmap.buff;
pic.xsize=bitmap.x_size;
pic.ysize=bitmap.y_size;
}else return -1;
}
else if (strcmp (p_str,".bmp")==0)
{
decode_bmp_struct dec={0};
dec.name=(u8 *)name;
dec.bmp=(BMP_DecodeStruct *)&bitmap;//这两个结构体是一样的,直接强制转换
ret=WORKING_DoWork (base,"BMP解码中。。。",decode_bmp,&dec);
if (ret==0)
{
pic.data=bitmap.buff;
pic.xsize=bitmap.x_size;
pic.ysize=bitmap.y_size;
}else return -1;
}
else if(strcmp (p_str,".png")==0)
{
decode_png_struct dec={0};
dec.name=name;
dec.pic=&pic;
ret=WORKING_DoWork (base,"PNG解码中。。。",decode_png,&dec);
if(ret==0)
return -1;
}
WIN_PhotoStruct *photo=0;
int x,y,xsize,ysize;
if (base)
{
//WIN_GetWinPosOnLcd (base,&x,&y,&xsize,&ysize);
x=0;y=0;xsize=base->x_size;ysize=base->y_size;
}
else
{
x=0;y=0;xsize=WIN_GetWinStruct()->lcd->getLcdSizeX();ysize=WIN_GetWinStruct()->lcd->getLcdSizeY();
}
if (pic.xsize<xsize) {x+=(xsize-pic.xsize)/2;xsize=pic.xsize;}
if (pic.ysize<ysize) {y+=(ysize-pic.ysize)/2;ysize=pic.ysize;}
//photo=WIN_CreatPhoto (0,0,x,y,xsize,ysize);
photo=WIN_CreatPhoto (base,0,x,y,xsize,ysize);
PHOTO_SetPic (photo,&pic);
WIN_ShowWindow((WIN_WindowStruct *)photo);
//int ret_= WIN_RunBlock ((WIN_WindowStruct *)photo);
int ret_=0;
//myfree (bitmap.buff);
photo->memData=bitmap.buff;
return ret_;
}
//显示点阵图像
int PHOTO_ShowPic (WIN_WindowStruct *base,WIN_PicStruct *pic)
{
WIN_PhotoStruct *photo=0;
int x,y,xsize,ysize;
if (base)
{
//WIN_GetWinPosOnLcd (base,&x,&y,&xsize,&ysize);
x=0;y=0;xsize=base->x_size;ysize=base->y_size;
}
else
{
x=0;y=0;xsize=WIN_GetWinStruct()->lcd->getLcdSizeX();ysize=WIN_GetWinStruct()->lcd->getLcdSizeY();
}
if (pic->xsize<xsize) {x+=(xsize-pic->xsize)/2;xsize=pic->xsize;}
if (pic->ysize<ysize) {y+=(ysize-pic->ysize)/2;ysize=pic->ysize;}
//photo=WIN_CreatPhoto (0,0,x,y,xsize,ysize);
photo=WIN_CreatPhoto (base,0,x,y,xsize,ysize);
PHOTO_SetPic (photo,pic);
photo->memData=mymalloc (photo->pic.xsize*photo->pic.ysize*2);
if (photo->memData)
{
mymemcpy (photo->memData,photo->pic.data,photo->pic.xsize*photo->pic.ysize*2);
photo->pic.data=photo->memData;
photo->win.pic.data=photo->memData;
}
WIN_ShowWindow((WIN_WindowStruct *)photo);
//int ret_= WIN_RunBlock ((WIN_WindowStruct *)photo);
int ret_=0;
return ret_;
}