//
|
// Created by YY on 2021/12/2.
|
//
|
|
#include <stdint.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdbool.h>
|
#include <string.h>
|
#include <pthread.h>
|
|
#include "watermark.h"
|
#include "charencode.h"
|
#include "ImageProc.h"
|
#include "apptimer.h"
|
|
//static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
|
typedef enum {
|
REVERSE,
|
BLACK,
|
WHITE,
|
RED,
|
GREEN,
|
BLUE
|
} color_t;
|
|
typedef struct {
|
int x;
|
} wm_t;
|
|
static char font_path[128] = {0};
|
static int wm_num = 0;
|
static wm_t *wm = NULL;
|
static int pic_width = 0, pic_height = 0;
|
static color_t wm_color;
|
|
static void PrintTime(apptimer_var_t val)
|
{
|
text_t text;
|
|
text.x = 10;
|
text.y = 10;
|
|
memset(text.text, 0, sizeof (text.text));
|
|
strcpy(text.text, FormatTime().c_str());
|
|
PrepareWatermark(RED, 24, 2, 1, &text);
|
|
AppTimer_add(PrintTime, D_SEC(1));
|
}
|
|
void InitWatermark(const char *font, int width, int height)
|
{
|
LOGI("InitWatermark");
|
if (font != NULL) {
|
strcpy(font_path, font);
|
}
|
|
if (wm != NULL) {
|
free(wm);
|
}
|
wm = (wm_t *)malloc(sizeof(wm_t) * 1000000);
|
wm_num = 0;
|
|
pic_width = width;
|
pic_height = height;
|
|
AppTimer_add(PrintTime, D_SEC(1));
|
}
|
|
void UninitWatermark(void)
|
{
|
LOGI("UninitWatermark");
|
if (wm != NULL) {
|
free(wm);
|
wm = NULL;
|
}
|
wm_num = 0;
|
AppTimer_delete(PrintTime);
|
}
|
|
void PrepareWatermark(int color, int font_size, int multiple, int num, const text_t *texts)
|
{
|
// const char school[] = "驾校:中華人民共和國 济源阳光驾校 aA5";
|
// const char teacher[] = "教练:黎利伯 让我们编译并运行上面的程序,并使用puts() 语句来重写文件";
|
// const char student[] = "学员:魏昭杰";
|
//
|
// const char speed[] = "42.6 km/h";
|
// const char czh[] = "豫U5966学";
|
//
|
// const char jwd[] = "35.086601 112.651904";
|
// const char date[] = "2021-10-22 15:45:36";
|
|
const int bytes_per_line = font_size / 8;
|
|
wm_num = 0;
|
wm_color = static_cast<color_t>(color);
|
|
//FILE *fp = fopen("/storage/self/primary/ms_unicode.bin", "rb");
|
//FILE *fp = fopen("/system/ms_unicode.bin", "rb");
|
FILE *fp = fopen(font_path, "rb");
|
if (fp != NULL) {
|
int offset = 0;
|
unsigned long unicode;
|
uint8_t zm[64*64/8]; // 最大
|
|
for (int m = 0; m < num; ++m) {
|
const char *str = texts[m].text;
|
|
int screen_x = texts[m].x;
|
int screen_y = texts[m].y;
|
offset = 0;
|
|
while (str != NULL && offset < strlen(str)) {
|
int skip = enc_utf8_to_unicode_one(reinterpret_cast<const unsigned char *>(str + offset), &unicode);
|
int next_x = 0;
|
|
if (skip == 0) {
|
// LOGI("水印文字编码错误");
|
break;
|
}
|
|
// 打印一个汉字或Asicc
|
fseek(fp, unicode * (font_size * font_size / 8), SEEK_SET);
|
fread(zm, 1, font_size * font_size / 8, fp);
|
// 32 * 32 点阵,每行占4字节
|
for (int i = 0; i < font_size * bytes_per_line; ++i) {
|
for (int j = 0; j < 8; ++j) {
|
if (zm[i] & (0x80 >> j)) {
|
// 得到点坐标
|
int x = (i % bytes_per_line) * 8 + j;
|
int y = i / bytes_per_line;
|
|
// 放大2倍 64 * 64
|
x *= multiple;
|
y *= multiple;
|
|
for (int a = 0; a < multiple; ++a) {
|
for (int b = 0; b < multiple; ++b) {
|
if (wm_num < 999999 && screen_y + y + a < pic_height && screen_x + x + b < pic_width) {
|
wm[wm_num].x =
|
((screen_y + y + a) * pic_width + screen_x + x +
|
b) * 4;
|
wm_num++;
|
}
|
if (x + b > next_x) {
|
next_x = x + b;
|
}
|
}
|
}
|
|
}
|
}
|
}
|
|
offset += skip;
|
if (next_x == 0) {
|
screen_x += font_size * multiple / 2; // 空格间距
|
} else {
|
screen_x += next_x + font_size * multiple / 12; // 字间距
|
}
|
}
|
}
|
fclose(fp);
|
}
|
}
|
|
void AddWatermark(uint8_t *mem)
|
{
|
switch (wm_color) {
|
case BLACK:
|
for (int i = 0; i < wm_num; ++i) {
|
mem[wm[i].x] = 0;
|
mem[wm[i].x + 1] = 0;
|
mem[wm[i].x + 2] = 0;
|
}
|
break;
|
case WHITE:
|
for (int i = 0; i < wm_num; ++i) {
|
mem[wm[i].x] = 0xFF;
|
mem[wm[i].x + 1] = 0xFF;
|
mem[wm[i].x + 2] = 0xFF;
|
}
|
break;
|
case RED:
|
for (int i = 0; i < wm_num; ++i) {
|
mem[wm[i].x] = 0xFF;
|
mem[wm[i].x + 1] = 0;
|
mem[wm[i].x + 2] = 0;
|
}
|
break;
|
case GREEN:
|
for (int i = 0; i < wm_num; ++i) {
|
mem[wm[i].x] = 0;
|
mem[wm[i].x + 1] = 0xFF;
|
mem[wm[i].x + 2] = 0;
|
}
|
break;
|
case BLUE:
|
for (int i = 0; i < wm_num; ++i) {
|
mem[wm[i].x] = 0;
|
mem[wm[i].x + 1] = 0;
|
mem[wm[i].x + 2] = 0xFF;
|
}
|
break;
|
case REVERSE:
|
default:
|
for (int i = 0; i < wm_num; ++i) {
|
mem[wm[i].x] ^= 0xFF;
|
mem[wm[i].x + 1] ^= 0xFF;
|
mem[wm[i].x + 2] ^= 0xFF;
|
}
|
break;
|
}
|
}
|