573 lines
12 KiB
C
573 lines
12 KiB
C
#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_;
|
||
}
|
||
|
||
|
||
|
||
|