• 图片叠加文字


    项目上有个小需求,在处理过和图片上叠加文字.本以为很简单.结果找字模都找了半天,找到了中英文又不通用.

    后来,又被图片的上下次序,字节正序倒序,按行,还是按列等搞的晕头转向......

    还好从网上下了个批量生成字模的软件"PCtoLCD2002.exe"

    自己写程序生成个GB2312编码表.

    主要是生成源码表.代码很简单,效率格式一律不考虑:

    1 int get_hzk_index(const char* str)
    2 {
    3 char ch;
    4 int n;
    5
    6 ch = *str;
    7
    8 if (ch < 0)
    9 {
    10 n = ch - 0xA1;
    11
    12 if (n > 14 && n < 87)
    13 {
    14 return ((n - 4) * 94 + str[1] - 0xA1) * 72;
    15 }
    16 else if (n < 9)
    17 {
    18 return (n * 94 + str[1] - 0xA1) * 72;
    19 }
    20 else
    21 {
    22 return -1;
    23 }
    24 }
    25
    26 return (9 * 94 + ch) * 72;;
    27 }
    28
    29
    30  int generate_src()
    31 {
    32 FILE *fp;
    33 int i, j;
    34 unsigned char buff[2];
    35
    36 fp = fopen("src.txt", "wb");
    37
    38 for (i = 0; i < 9; i ++)
    39 {
    40 for (j = 0; j < 94; j ++)
    41 {
    42 buff[0] = i + 0xA1;
    43 buff[1] = j + 0xA1;
    44 fwrite(buff, 2, 1, fp);
    45 }
    46 }
    47
    48
    49 for (i = 0; i < 128; i ++)
    50 {
    51 if (isprint(i))
    52 {
    53 buff[0] = i;
    54 }
    55 else
    56 {
    57 buff[0] = ' ';
    58 }
    59 buff[1] = ' ';
    60 fwrite(buff, 2, 1, fp);
    61 }
    62
    63 for (i = 0; i < 60; i ++)
    64 {
    65 buff[0] = ' ';
    66 buff[1] = ' ';
    67 fwrite(buff, 2, 1, fp);
    68 }
    69
    70 for (i = 15; i < 87; i ++)
    71 {
    72 for (j = 0; j < 94; j ++)
    73 {
    74 buff[0] = i + 0xA1;
    75 buff[1] = j + 0xA1;
    76 fwrite(buff, 2, 1, fp);
    77 }
    78 }
    79
    80 fclose(fp);
    81
    82 return 0;
    83 }

    09 10区本来是空的..我把英文的前128个写了进去..为了方便处理每个英文字符后面跟一个空格.

    这样的话就和汉字对齐了.

    后面的汉字区,按空间往前移.详细的看get_hzk_index函数.

    然后通过上述软件把src.txt变为字模文件 (阴码,按列,逆向)  按列主要是处理英文..要不很麻烦.

    生成des.txt....然后用EDITPLUS,调格式.去{}等....最后生成一个数组

    写入文件 hzk24.h

    再用FREEIMAGE把JPG解码,,自己写函数叠加

    1 extern unsigned char g_hzk24[561744];
    2
    3
    4  /**
    5 * @brief 载入任何可能的图像文件
    6 * @param fname {const char *} [in] 所要载入文件名
    7 * @return {FIBITMAP *} 成功返回句柄 不成功NULL
    8 */
    9 FIBITMAP* ImageLoad(const char* fname)
    10 {
    11 FREE_IMAGE_FORMAT fif;
    12 FIBITMAP *dib;
    13
    14 /* 文件名称非法,直接返回 */
    15 if (fname == NULL || strlen(fname) < 2)
    16 {
    17 fprintf(stderr, "非法文件名\n");
    18 return NULL;
    19 }
    20
    21 /* 从文件结构判断类型 */
    22 if ((fif = FreeImage_GetFileType(fname, 0)) == FIF_UNKNOWN)
    23 {
    24 fprintf(stderr, "无法从结构本身判断文件类型\n");
    25
    26 /* 如果从结构判断不成功,改为从扩展名判断 */
    27 if ((fif = FreeImage_GetFIFFromFilename(fname)) == FIF_UNKNOWN)
    28 {
    29 fprintf(stderr, "无法从扩展名判断类型\n");
    30 /* 依然不成功 */
    31 return NULL;
    32 }
    33 }
    34
    35 if (!FreeImage_FIFSupportsReading(fif))
    36 {
    37 /* 不支持该类型 */
    38 fprintf(stderr, "不支持该类型\n");
    39 return NULL;
    40 }
    41
    42 /* 载入文件 */
    43 if ((dib = FreeImage_Load(fif, fname, 0)) == NULL)
    44 {
    45 fprintf(stderr, "无法载入文件\n");
    46 return NULL;
    47 }
    48
    49 return dib;
    50 }
    51
    52  /**
    53 * @brief 释放图像
    54 * @param dib {FIBITMAP *} [in] 输入句柄
    55 * @return {void} 无返回值
    56 */
    57  void ImageUnload(FIBITMAP *dib)
    58 {
    59 if (dib != NULL)
    60 {
    61 /* 释放内存 */
    62 FreeImage_Unload(dib);
    63 }
    64 }
    65
    66
    67  /**
    68 * @brief 获得字符在字模表中的地址
    69 * @param str {const char *} [in] 输入字符
    70 * @return {int} 成功返回地址 不成功-1
    71 */
    72  int get_hzk_index(const char* str)
    73 {
    74 char ch;
    75 int n;
    76
    77 /* 字符非法 */
    78 if (str == NULL || str[0] == 0)
    79 {
    80 return -1;
    81 }
    82
    83 ch = *str;
    84
    85 /* 中文 */
    86 if (ch < 0)
    87 {
    88 n = (unsigned char)ch - 0xA1;
    89
    90 /* 汉字 */
    91 if (n > 14 && n < 87)
    92 {
    93 return ((n - 4) * 94 + (unsigned char)str[1] - 0xA1) * 72;
    94 }
    95 /* 中文符号 */
    96 else if (n < 9)
    97 {
    98 return (n * 94 + (unsigned char)str[1] - 0xA1) * 72;
    99 }
    100 else
    101 {
    102 return -1;
    103 }
    104 }
    105
    106 /* 英文 */
    107 return (9 * 94 + ch) * 72;;
    108 }
    109
    110  /**
    111 * @brief 在图片文件上叠加文字
    112 * @param src {const char *} [in] 输入文件
    113 * @param des {const char *} [in] 输出文件
    114 * @param sx {int} [in] 起始X像素(以1开始,下同)
    115 * @param sy {int} [in] 起始Y像素
    116 * @param str {const char *} [in] 所要叠加的字符串
    117 * @return {int} 成功 0 否则 -1
    118 */
    119  int img_draw_text(const char *src, const char *des, int sx, int sy, const char *str)
    120 {
    121 int loc;
    122 FIBITMAP *dib;
    123 int width, height, pitch, bpp;
    124 int i, j, k, m, n, x, y;
    125 int len;
    126 unsigned char *img, *ptr1, *ptr2;
    127 unsigned char pix[4];
    128
    129
    130 /* 参数非法 */
    131 if (src == NULL || strlen(src) < 2 || \
    132 des == NULL || strlen(des) < 2 || \
    133 str == NULL || strlen(str) < 2 || \
    134 sx < 1)
    135 {
    136 return -1;
    137 }
    138
    139 /* 无法载入图片 */
    140 if ((dib = ImageLoad(src)) == NULL)
    141 {
    142 return -1;
    143 }
    144
    145 width = FreeImage_GetWidth(dib);
    146 height = FreeImage_GetHeight(dib);
    147 pitch = FreeImage_GetPitch(dib);
    148 bpp = FreeImage_GetBPP(dib) >> 3;
    149
    150 /* 计算起始X,Y(像素位置) */
    151 x = (sx - 1);
    152
    153 if (sy < 0)
    154 {
    155 y = -1 - sy;
    156 }
    157 else
    158 {
    159 y = height - sy;
    160 }
    161
    162 if (x >= width || y < 23 || y > height - 1)
    163 {
    164 ImageUnload(dib);
    165 return -1;
    166 }
    167
    168 /* 得出一点 */
    169 memset(pix, 255, sizeof(pix));
    170
    171 /* 求出内存中图像矩阵位置 */
    172 img = (unsigned char *)FreeImage_GetBits(dib);
    173
    174 /* 遍历字符串 */
    175 len = strlen(str);
    176
    177 for (i = 0; i < len; i ++)
    178 {
    179 /* 求出字模位置 */
    180 loc = get_hzk_index(str + i);
    181 ptr1 = g_hzk24 + loc;
    182
    183 /* 中文 */
    184 if (str[i] < 0)
    185 {
    186 if (x + 24 > width)
    187 {
    188 ptr2 = img + y * pitch + x * bpp;
    189
    190 for (n = 0; n < 24; n ++)
    191 {
    192 memset(ptr2 - n * pitch, 0, (width - x) * bpp);
    193 }
    194
    195 x = 0;
    196 y -= 24;
    197 }
    198
    199 if (y < 23)
    200 {
    201 break;
    202 }
    203
    204 // 在XY处画
    205   ptr2 = img + y * pitch + x * bpp;
    206
    207 for (m = 0; m < 24; m ++)
    208 {
    209 for (j = 0; j < 3; j ++)
    210 {
    211 for(k = 0; k < 8; k ++)
    212 {
    213 if (ptr1[m * 3 + j] & (0x01 << k))
    214 {
    215 memcpy(ptr2 + (-j * 8 - k) * pitch + m * bpp, pix, bpp);
    216 }
    217 else
    218 {
    219 memset(ptr2 + (-j * 8 - k) * pitch + m * bpp, 0, bpp);
    220 }
    221 }
    222 }
    223 }
    224
    225 x += 24;
    226
    227 i ++;
    228 }
    229 /* 英文 */
    230 else
    231 {
    232 if (x + 12 > width)
    233 {
    234 ptr2 = img + y * pitch + x * bpp;
    235
    236 for (n = 0; n < 24; n ++)
    237 {
    238 memset(ptr2 - n * pitch, 0, (width - x) * bpp);
    239 }
    240
    241 x = 0;
    242 y -= 24;
    243 }
    244
    245 if (y < 23)
    246 {
    247 break;
    248 }
    249
    250 ptr2 = img + y * pitch + x * bpp;
    251
    252 for (m = 0; m < 12; m ++)
    253 {
    254 for (j = 0; j < 3; j ++)
    255 {
    256 for(k = 0; k < 8; k ++)
    257 {
    258 if (ptr1[m * 3 + j] & (0x01 << k))
    259 {
    260 memcpy(ptr2 + (-j * 8 - k) * pitch + m * bpp, pix, bpp);
    261 }
    262 else
    263 {
    264 memset(ptr2 + (-j * 8 - k) * pitch + m * bpp, 0, bpp);
    265 }
    266 }
    267 }
    268 }
    269
    270 x += 12;
    271 }
    272 }
    273
    274 if (x < width && y >= 23)
    275 {
    276 ptr2 = img + y * pitch + x * bpp;
    277 width -= x;
    278 width *= bpp;
    279
    280 for (i = 0; i < 24; i ++)
    281 {
    282 memset(ptr2 - i * pitch, 0, width);
    283 }
    284 }
    285
    286 FreeImage_Save(FIF_JPEG, dib, des, 0);
    287 FreeImage_Unload(dib);
    288 return 0;
    289 }

    至此大功告成..呵呵...

  • 相关阅读:
    FreeMarker缓存处理
    freemarker入门实例与源码研究准备工作
    Freemarker常用技巧(二)
    Freemarker常用技巧(一)
    Hessian与Spring整合
    Hessian学习
    数组常见的面试题
    关于排序的实现
    Redis与Memcache的区别
    JDBC编程步骤
  • 原文地址:https://www.cnblogs.com/javado/p/1892007.html
Copyright © 2020-2023  润新知