Files
player/Project/Src/MyWinApp/mywin_user_photo.c
2025-07-05 19:47:28 +08:00

573 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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_;
}