//#define LOG_NDEBUG 0
#define LOG_TAG "WaterMark"
#include <fstream>
#include <iostream>
#include <vector>
#include <ctime>
#include <sys/mman.h>
#include <libyuv.h>
#include <utils/Errors.h>
#include <log/log.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "watermark.h"
namespace android {
namespace IspCamera {
WaterMark::WaterMark()
{
for(int i = 0; i < MAX_ICON_NUM; i++)
{
icon_arry[i].id = i;
icon_arry[i].width = 0;
icon_arry[i].height = 0;
icon_arry[i].y = NULL;
icon_arry[i].alph = NULL;
icon_arry[i].c = NULL;
}
msinglewm = {200, 200, "0123456789ABC"};
ALOGE("construct WaterMark exit\n");
}
WaterMark::~WaterMark()
{
for(int i = 0; i < MAX_ICON_NUM; i++){
if(icon_arry[i].y != NULL)
free(icon_arry[i].y);
}
ALOGE("delete WaterMark\n");
}
void WaterMark::ARGB8888ToYUV420sp(unsigned char *src_p, int width, int height, unsigned char *dest_y,
unsigned char *dest_c, unsigned char *dest_alph)
{
int i,j;
for(i = 0; i < (int)height; i++) {
if((i&1) == 0) {
for(j= 0; j< (int)width; j++) {
*dest_y = (299*src_p[2]+587*src_p[1]+114*src_p[0])/1000;
if((j&1) == 0)
*dest_c++ = 128+(564*(src_p[0]-*dest_y)/1000); //cb
else
*dest_c++ = 128+(713*(src_p[2]-*dest_y)/1000); //cr
*dest_alph++ = src_p[3];
src_p +=4;
dest_y++;
}
} else {
for(j= 0; j< (int)width; j++) {
*dest_y = (299*src_p[2]+587*src_p[1]+114*src_p[0])/1000;
*dest_alph++ = src_p[3];
src_p +=4;
dest_y++;
}
}
}
return;
}
int WaterMark::InitwWaterMark()
{
FILE *fp = NULL;
int i;
int pic_width = 0, pic_height = 0;
char filename[256];
unsigned char *argb_buf = NULL;
for(i = 0; i < MAX_ICON_NUM; i++) {
sprintf(filename, "%s/argb8888_24x32_%d.bmp", WATERMARK_BMP_DIR, i);
ALOGE("open file %s\n", filename);
fp = fopen(filename, "r");
if(NULL == fp) {
ALOGE("Fail to open file %s(%s)!", filename, strerror(errno));
goto OPEN_FILE_ERR;
}
icon_arry[i].id = i;
fseek(fp, 18, SEEK_SET);
fread(&pic_width, 1, 4, fp);
fread(&pic_height, 1, 4, fp);
icon_arry[i].width = abs(pic_width);
icon_arry[i].height = abs(pic_height);
ALOGE("real width=%d(%d), height=%d(%d)\n", icon_arry[i].width, pic_width, icon_arry[i].height, pic_height);
icon_arry[i].y = (unsigned char*)malloc(icon_arry[i].width * icon_arry[i].height*5/2);
if(NULL == icon_arry[i].y) {
ALOGE("malloc picture yuv fail !\n");
fclose(fp);
goto ALLOC_Y_ERR;
}
memset(icon_arry[i].y, 0xff, (icon_arry[i].width * icon_arry[i].height*5/2));
icon_arry[i].alph = icon_arry[i].y + icon_arry[i].width * icon_arry[i].height;
icon_arry[i].c = icon_arry[i].alph + icon_arry[i].width * icon_arry[i].height;
argb_buf = (unsigned char *)malloc(icon_arry[i].width * icon_arry[i].height * 4);
if (NULL == argb_buf) {
ALOGE("malloc bmp buf fail !\n");
fclose(fp);
goto ALLOC_BUF_ERR;
}
fseek(fp, 54, SEEK_SET);
fread(argb_buf, icon_arry[i].width * icon_arry[i].height * 4, 1, fp);
ARGB8888ToYUV420sp(argb_buf, icon_arry[i].width, icon_arry[i].height,
icon_arry[i].y, icon_arry[i].c, icon_arry[i].alph);
fclose(fp);
free(argb_buf);
}
return 0;
ALLOC_BUF_ERR:
ALLOC_Y_ERR:
OPEN_FILE_ERR:
for(i = 0; i < MAX_ICON_NUM; ++i) {
if(icon_arry[i].y != NULL) {
free(icon_arry[i].y);
icon_arry[i].y = NULL;
}
}
return -1;
}
int WaterMark::GetWordNum(char val)
{
int i;
int cnt = 0;
for(i=7; i>=0; i--) {
if(!(val & (1<<i)))
break;
else
cnt++;
}
if (cnt == 0)
return 1;
return cnt;
}
#define DEFAULT_NUM 36
int WaterMark::GetWordIndex(char *data, int wordlen)
{
int index = DEFAULT_NUM;
if(wordlen == 1) {
if (*data >= '0' && *data <= '9') {
ALOGE("choose numben 0 ~ 9\n");
index = (*data - 48); //落在数组下标0开始
} else if (*data >= 'A' && *data <= 'Z') {
ALOGE("choose A~Z\n");
index = (*data - 55); //落在数组下标10开始
} else if (*data == ' ') {
ALOGE("choose kong\n");
index = 36;
} else if (*data == '-') {
ALOGE("choose -\n");
index = 37;
} else if (*data == '.') {
ALOGE("choose .\n");
index = DEFAULT_NUM;
} else if (*data == ':') {
ALOGE("choose eng :\n");
index = 38;
} else if (*data == '/') {
ALOGE("choose /\n");
index = 39;
} else {
ALOGE("not match %s , use DEFAULT_NUM\n", data);
index = DEFAULT_NUM;
}
} else if (wordlen == 3) {
if(!memcmp(data, "京", 3)) {
ALOGE("choose %s\n", "京");
index = 40;
} else if (!memcmp(data, "沪", 3)) {
ALOGE("choose %s\n", "沪");
index = 41;
} else if (!memcmp(data, ":", 3)) {
ALOGE("choose chn :\n");
index = 38;
} else {
ALOGE("choose DEFAULT_NUM\n");
index = DEFAULT_NUM;
}
}
ALOGE("\twordlen -> %d, index -> %d\n", wordlen, index);
return index;
}
void WaterMark::Yuv420spBlending(unsigned char *bg_y, unsigned char *bg_c, int bg_width, int bg_height,
int left, unsigned int top, int fg_width, int fg_height,
unsigned char *fg_y, unsigned char *fg_c, unsigned char *alph)
{
unsigned char *bg_y_p = NULL;
unsigned char *bg_c_p = NULL;
int i = 0;
int j = 0;
bg_y_p = bg_y + top * bg_width + left;
bg_c_p = bg_c + (top >>1)*bg_width + left;
for(i = 0; i<(int)fg_height; i++) {
if((i&1) == 0) {
for(j=0; j< (int)fg_width; j++) {
*bg_y_p = ((256 - *alph)*(*bg_y_p) + (*fg_y++)*(*alph))>>8;
*bg_c_p = ((256 - *alph)*(*bg_c_p) + (*fg_c++)*(*alph))>>8;
alph++;
bg_y_p++;
bg_c_p++;
}
bg_c_p = bg_c_p + bg_width - fg_width;
} else {
for(j=0; j< (int)fg_width; j++) {
*bg_y_p = ((256 - *alph)*(*bg_y_p) + (*fg_y++)*(*alph))>>8;
alph++;
bg_y_p++;
}
}
bg_y_p = bg_y_p + bg_width - fg_width;
}
}
int WaterMark::PushWm2bg(unsigned char *bg_y_buf, unsigned char *bg_c_buf, int bg_width, int bg_height, struct disp_content *single_wm)
{
int pos_x;
struct backgroud_info bg_info;
int buflen, wordlen;
char *p_content;
int pic_index;
int i;
bg_info.width = bg_width;
bg_info.height = bg_height;
bg_info.y = bg_y_buf;
bg_info.c = bg_c_buf;
p_content = single_wm->content;
buflen = strlen(single_wm->content);
pos_x = single_wm->x;
ALOGE("\nshow: %s(%d Bytes):\n", p_content, buflen);
for (i = 0; i < strlen(single_wm->content); i++) {
wordlen = GetWordNum(p_content[0]);
buflen -= wordlen;
if(buflen < 0) break;
pic_index = GetWordIndex(p_content, wordlen);
Yuv420spBlending(bg_info.y, bg_info.c, bg_info.width, bg_info.height, pos_x,