在图片中添加自己的文本信息(PNG及JPEG格式)

在图片中添加自己的文本信息(PNG及JPEG格式)

背景:

PNG格式和JPEG格式的图片都有一个表示文本信息的段,这些信息可以是任意的字符串,或者版权信息,或者工作室信息,或者其它的。本文的程序是在原始图片中添加这个段的信息。由于比较简单,不多说。

对比图片格式,小弟学习过一段时间,由于工作原因,对JPEG了解深一些,但只限于格式,像JPEG的压缩算法还没学习到。

代码如下:

/**************************************************************************

PNG:

段组成:

名称 占用字节 内容

长度 4 数据长度

段名 4 如:'IHDR'

数据 N 数据内容

CRC 4 CRC32值(段名及数据的CRC)

添加文本信息:

长度: strlen(text)

段名:'tEXt'

数据: text(内容自定)

CRC: crc32('tEXt'+text)

放置位置:位于IHDR后面

PNG头8字节,IHDR段25字节(内容13字节,其它12字节),共33字节,

故放置33偏移量处后面。

JPEG:

组成:

名称 占用字节 内容

段名 2 如:FF D8表示JPEG图片,FF FE表示注释段

长度 2 数据段长度+2(即这里的2字节)

数据 N 数据内容

添加文件信息:

段名: FF FE

长度: strlen(text_len) + 2

数据: info(text)

放置位置:位于FF E0或FF E1段后面

读0x04、0x05处长度(即FFE0或FFE1的长度),须转换成小端模式

PNG、JPEG图片为大端模式,以字节保存没问题,但数据长度必须转换成大端模式

写新文件方法:

先保存原来的开始部分,再插入文本信息,再保存剩下部分数据

**************************************************************************/

#include

#include

#include

#include "crc.h"

const char *text = ">AUTHOR: Late Lee from http://www.latelee.org.\n";

#define little2big32(x) \

( (x&0xff000000) >> 24 | (x&0xff0000) >> 8 | (x&0xff00) << 8 | (x&0xff) << 24 )

#define little2big16(x) \

( (x&0xff00) >> 8 | (x&0xff) << 8 )

#define HEAD_SIZE 33

int add_text_png(const char *file, const char *new_file)

{

FILE *in;

FILE *out;

int len = 0;

size_t ret = 0;

char *buffer;

char *text_buf;

size_t text_len = 0;

size_t text_len_1 = 0;

char text_type[4] = {'t', 'E', 'X', 't'};

int text_crc = 0;

in = fopen(file, "rb");

if (in == NULL)

{

printf("Can not open file %s\n", file);

return -1;

}

fseek(in, 0, SEEK_END);

len = ftell(in);

fseek(in, 0, SEEK_SET);

printf("file size: %d\n", len);

buffer = (char *)malloc(sizeof(char) * len);

if (buffer == NULL)

{

return -1;

}

// read all to buffer

ret = fread(buffer, 1, len, in);

if (ret != len)

{

printf("read file failed.\n");

return -1;

}

out = fopen(new_file, "wb");

if (out == NULL)

{

printf("open new file failed.\n");

return -1;

}

// write 'head'

ret = fwrite(buffer, 1, HEAD_SIZE, out);

if (ret != HEAD_SIZE)

{

printf("write head failed.\n");

return -1;

}

/////////////////////////

text_len = strlen(text);

text_buf = (char *)malloc(sizeof(char) * (text_len + 12));

text_len_1 = little2big32(text_len);

memcpy(text_buf, &text_len_1, 4); // big endian

memcpy(text_buf + 4, text_type, 4);

memcpy(text_buf + 4 + 4, text, text_len);

text_crc = crc32((unsigned char *)(text_buf + 4), (u32)text_len + 4);

memcpy(text_buf + 4 + 4 + text_len, &text_crc, 4);

printf("text len: %d\n", text_len);

// write information

ret = fwrite(text_buf, 1, text_len + 12, out);

if (ret != text_len + 12)

{

printf("write head failed.\n");

return -1;

}

// write 'left'

ret = fwrite(buffer + HEAD_SIZE, 1, len - HEAD_SIZE, out);

if (ret != len - HEAD_SIZE)

{

printf("write head failed.\n");

return -1;

}

fclose(in);

fclose(out);

free(buffer);

free(text_buf);

printf("good job.\n");

return 0;

}

int add_text_jpeg(const char *file, const char *new_file)

{

FILE *in;

FILE *out;

int len = 0;

size_t ret = 0;

unsigned char *buffer; // must be unsigned char

char *text_buf;

size_t text_len = 0;

size_t text_len_1 = 0;

size_t tmp_len = 0;

unsigned char text_type[2] = {0xFF, 0xFE};

in = fopen(file, "rb");

if (in == NULL)

{

printf("Can not open file %s\n", file);

return -1;

}

fseek(in, 0, SEEK_END);

len = ftell(in);

fseek(in, 0, SEEK_SET);

printf("file size: %d\n", len);

buffer = (unsigned char *)malloc(sizeof(char) * len);

if (buffer == NULL)

{

return -1;

}

// read all to buffer

ret = fread(buffer, 1, len, in);

if (ret != len)

{

printf("read file failed.\n");

return -1;

}

// read tmp_len

tmp_len = *(buffer + 4) << 8 | *(buffer + 5);

printf("tmp len: %x\n", tmp_len);

out = fopen(new_file, "wb");

if (out == NULL)

{

printf("open new file failed.\n");

return -1;

}

// write 'head'

ret = fwrite(buffer, 1, tmp_len + 4, out);

if (ret != tmp_len + 4)

{

printf("write head failed.\n");

return -1;

}

/////////////////////////

text_len = strlen(text);

text_buf = (char *)malloc(sizeof(char) * (text_len + 4));

text_len_1 = little2big16(text_len + 2);

memcpy(text_buf, text_type, 2); // FF FE

memcpy(text_buf + 2, &text_len_1, 2); // len

memcpy(text_buf + 2 + 2, text, text_len); // text

printf("text len: %d\n", text_len);

// write information

ret = fwrite(text_buf, 1, text_len + 4, out);

if (ret != text_len + 4)

{

printf("write text failed.\n");

return -1;

}

// write 'left'

ret = fwrite(buffer + tmp_len + 4, 1, len - (tmp_len + 4), out);

if (ret != len - (tmp_len + 4))

{

printf("write file failed.\n");

return -1;

}

fclose(in);

fclose(out);

free(buffer);

free(text_buf);

printf("good job.\n");

return 0;

}

int my_strnicmp(const char *s1, const char *s2, size_t len)

{

unsigned char c1, c2;

const char *tmp1 = s1 + strlen(s1) - 1;

const char *tmp2 = s2 + strlen(s2) - 1;

c1 = 0; c2 = 0;

if (len) {

do {

c1 = *tmp1; c2 = *tmp2;

tmp1--; tmp2--;

if (!c1)

break;

if (!c2)

break;

if (c1 == c2)

continue;

c1 = tolower(c1);

c2 = tolower(c2);

if (c1 != c2)

break;

} while (--len);

}

return (int)c1 - (int)c2;

}

// a.exe foo.jpg bar.jpg

// 其中的图片格式需要一致,由用户控制

int main(int argc, char *argv[])

{

int ret = 0;

if (argc != 3)

{

printf("usage: %s old.jpg|png new.jpg|png.\n", argv[0]);

return -1;

}

if (!my_strnicmp(argv[1], "jpg", 3))

add_text_jpeg(argv[1], argv[2]);

else if (!my_strnicmp(argv[1], "png", 3))

add_text_png(argv[1], argv[2]);

else

{

printf("not support.\n");

return -1;

}

return 0;

}

✨ 相关推荐

王健林的至暗时刻与万达的救赎之路:从柏文喜大资管理论看商业帝国的重构
惹女人生气了,别只会说“对不起”,这样哄才管用_手机网易网
三国著名将领高顺介绍 高顺字什么
下载旧版本彩票365软件

三国著名将领高顺介绍 高顺字什么

📅 08-29 👀 4025