惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
T
Threatpost
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
V2EX - 技术
V2EX - 技术
D
Docker
G
Google Developers Blog
Microsoft Security Blog
Microsoft Security Blog
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
The GitHub Blog
The GitHub Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
T
Troy Hunt's Blog
Webroot Blog
Webroot Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
量子位
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
F
Full Disclosure
B
Blog
O
OpenAI News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
Google DeepMind News
Google DeepMind News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security
Know Your Adversary
Know Your Adversary
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
Scott Helme
Scott Helme
T
The Exploit Database - CXSecurity.com
博客园 - 聂微东
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The Last Watchdog
The Last Watchdog
Recorded Future
Recorded Future
IT之家
IT之家
Project Zero
Project Zero
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Attack and Defense Labs
Attack and Defense Labs
L
Lohrmann on Cybersecurity
SecWiki News
SecWiki News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

浮生笔记

时机的重要性 回答dayu博客的几个问题 学会做选择 我理想的城市 如何选择一个适合的城市 马来西亚游记 回首2023,展望2024 从ChatGPT聊起 菲律宾旅游攻略笔记 深圳游记 香港游记 怎样赚钱----我理解的商业模式 用户界面与跨平台 使用telnet通过IMAP协议读取QQ邮箱 信息成本-----从ChatGPT到情报学 买断制到订阅制----兼谈消费频次 我眼中的CSDN 迁移博客内容到静态博客 Hugo使用Jane主题支持搜索实现 C语言和Lua的相互调用示例代码 从放逐之城看经济学 不同产业的分析 回首2021,展望2022 游戏中的经济学 Windows获取网络地址、子网掩码等 -fsanitize=address 参数作用 C++ 编译器支持标准判断 C++ 编译器支持标准判断 VS Code的golang开发配置 之 代码提示 二叉树遍历的非递归算法的实现 我的Chrome插件 golang 获取get参数 关于写代码的几个看法 golang编程之我见 Linux 网络编程之 Select 构建之法读书笔记 (1) 友情链接 Effective Morden C++ 读书笔记(3) 二进制协议 vs 文本协议 从重构到重写 asio制作使用ssl通信的证书 gdb 7.11 Linux 获取网卡信息 《构建之法》读后感 由买冰箱想到的 2014年年终总结 聊聊我对写好程序的认识 经验搜索排名---google已经做过类似的了(我想多了) 有关编程语言的认识
编程技巧之表格驱动编程
DennisThink · 2014-07-27 · via 浮生笔记
/* Image format-dependent operations. */

typedef struct {

	jas_image_t *(*decode)(jas_stream_t *in, char *opts);
	/* Decode image data from a stream. */

	int (*encode)(jas_image_t *image, jas_stream_t *out, char *opts);
	/* Encode image data to a stream. */

	int (*validate)(jas_stream_t *in);
	/* Determine if stream data is in a particular format. */

} jas_image_fmtops_t;

/* Image format information. */

typedef struct {

	int id;
	/* The ID for this format. */

	char *name;
	/* The name by which this format is identified. */

	char *ext;
	/* The file name extension associated with this format. */

	char *desc;
	/* A brief description of the format. */

	jas_image_fmtops_t ops;
	/* The operations for this format. */

} jas_image_fmtinfo_t;

这段代码是从jasper的源代码中摘抄出来的,jas_image_fmtops_t 这个结构体定义了三个函数指针,是对图像的基本操作。s_image_fmtinfo_t 描述了一个图片的最基本的属性。包括id号,格式定义等。刚刚开始的时候我不明白为什么id不定义成枚举类型,而要定义成int。当我看到下面的代码的时候,我知道了。

我们接着看下面的代码

jas_init

/* Initialize the image format table. */
int jas_init()
{
	jas_image_fmtops_t fmtops;
	int fmtid;

	fmtid = 0;

#if !defined(EXCLUDE_MIF_SUPPORT)
	fmtops.decode = mif_decode;
	fmtops.encode = mif_encode;
	fmtops.validate = mif_validate;
	jas_image_addfmt(fmtid, "mif", "mif", "My Image Format (MIF)", &fmtops);
	++fmtid;
#endif

#if !defined(EXCLUDE_PNM_SUPPORT)
	fmtops.decode = pnm_decode;
	fmtops.encode = pnm_encode;
	fmtops.validate = pnm_validate;
	jas_image_addfmt(fmtid, "pnm", "pnm", "Portable Graymap/Pixmap (PNM)",
	  &fmtops);
	jas_image_addfmt(fmtid, "pnm", "pgm", "Portable Graymap/Pixmap (PNM)",
	  &fmtops);
	jas_image_addfmt(fmtid, "pnm", "ppm", "Portable Graymap/Pixmap (PNM)",
	  &fmtops);
	++fmtid;
#endif

#if !defined(EXCLUDE_BMP_SUPPORT)
	fmtops.decode = bmp_decode;
	fmtops.encode = bmp_encode;
	fmtops.validate = bmp_validate;
	jas_image_addfmt(fmtid, "bmp", "bmp", "Microsoft Bitmap (BMP)", &fmtops);
	++fmtid;
#endif

#if !defined(EXCLUDE_RAS_SUPPORT)
	fmtops.decode = ras_decode;
	fmtops.encode = ras_encode;
	fmtops.validate = ras_validate;
	jas_image_addfmt(fmtid, "ras", "ras", "Sun Rasterfile (RAS)", &fmtops);
	++fmtid;
#endif

#if !defined(EXCLUDE_JP2_SUPPORT)
	fmtops.decode = jp2_decode;
	fmtops.encode = jp2_encode;
	fmtops.validate = jp2_validate;
	jas_image_addfmt(fmtid, "jp2", "jp2",
	  "JPEG-2000 JP2 File Format Syntax (ISO/IEC 15444-1)", &fmtops);
	++fmtid;
	fmtops.decode = jpc_decode;
	fmtops.encode = jpc_encode;
	fmtops.validate = jpc_validate;
	jas_image_addfmt(fmtid, "jpc", "jpc",
	  "JPEG-2000 Code Stream Syntax (ISO/IEC 15444-1)", &fmtops);
	++fmtid;
#endif

#if !defined(EXCLUDE_JPG_SUPPORT)
	fmtops.decode = jpg_decode;
	fmtops.encode = jpg_encode;
	fmtops.validate = jpg_validate;
	jas_image_addfmt(fmtid, "jpg", "jpg", "JPEG (ISO/IEC 10918-1)", &fmtops);
	++fmtid;
#endif

#if !defined(EXCLUDE_PGX_SUPPORT)
	fmtops.decode = pgx_decode;
	fmtops.encode = pgx_encode;
	fmtops.validate = pgx_validate;
	jas_image_addfmt(fmtid, "pgx", "pgx", "JPEG-2000 VM Format (PGX)", &fmtops);
	++fmtid;
#endif

	/* We must not register the JasPer library exit handler until after
	at least one memory allocation is performed.  This is desirable
	as it ensures that the JasPer exit handler is called before the
	debug memory allocator exit handler. */
	atexit(jas_cleanup);

	return 0;
}
  

int jas_image_addfmt(int id, char *name, char *ext, char *desc,
  jas_image_fmtops_t *ops)
{
	jas_image_fmtinfo_t *fmtinfo;
	assert(id >= 0 && name && ext && ops);
	if (jas_image_numfmts >= JAS_IMAGE_MAXFMTS) {
		return -1;
	}
	fmtinfo = &jas_image_fmtinfos[jas_image_numfmts];
	fmtinfo->id = id;
	if (!(fmtinfo->name = jas_strdup(name))) {
		return -1;
	}
	if (!(fmtinfo->ext = jas_strdup(ext))) {
		jas_free(fmtinfo->name);
		return -1;
	}
	if (!(fmtinfo->desc = jas_strdup(desc))) {
		jas_free(fmtinfo->name);
		jas_free(fmtinfo->ext);
		return -1;
	}
	fmtinfo->ops = *ops;
	++jas_image_numfmts;
	return 0;
}

jas_image_fmtinfos 是jas_image_fmtinfo_t类型的数组。

答案即将揭晓: 从上面的代码可以看出,作者使用了表格驱动编程。全局变量jas_image_fmtinfos 保存了所有支持的图片格式的全部信息。而每次要对某种格式进行添加或者删除的时候,只用修改jas_init的代码就可以了,而且格式的编号是动态的。每次进行使用的时候去该数组中查找就可以了。 下面看看使用的代码,这段函数是根据后缀名查询编号的。

int jas_image_fmtfromname(char *name)
int jas_image_fmtfromname(char *name)
{
	int i;
	char *ext;
	jas_image_fmtinfo_t *fmtinfo;
	/* Get the file name extension. */
	if (!(ext = strrchr(name, '.'))) {
		return -1;
	}
	++ext;
	/* Try to find a format that uses this extension. */	
	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i,
	  ++fmtinfo) {
		/* Do we have a match? */
		if (!strcmp(ext, fmtinfo->ext)) {
			return fmtinfo->id;
		}
	}
	return -1;
}

  从上面的代码可以看出,每次查询后缀对应的格式的时候,去比较当前的后缀名和jas_image_fmtinfos 数组中对应的后缀名,来确定id好,扩展性极好。

文章作者 DennisThink

上次更新 2014-07-27

许可协议 CC BY-NC-ND 4.0