478 lines
14 KiB
C
478 lines
14 KiB
C
#include "mywin_user_photo.h"
|
||
#include "bmp.h"
|
||
#include "ff.h"
|
||
#include "mywin_inc.h"
|
||
#include "picdeco.h"
|
||
#include "png.h"
|
||
#include "system_file.h"
|
||
#include <zlib.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;
|
||
uint16_t *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 uint16_t 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 uint16_t 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 uint16_t 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) {
|
||
uint16_t *ptr = photo->memDataBit;
|
||
uint16_t *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++) {
|
||
uint16_t 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 {
|
||
uint8_t *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 {
|
||
uint8_t *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};
|
||
uint8_t 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 = (uint8_t *)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 = (uint8_t *)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_;
|
||
}
|