源代码分析 向PNG格式的图片文件写入的代码阅读
写优秀的代码之前,要大量阅读优秀的源代码,然后反复地写代码进行练习,
并分析什么样的代码是好代码。下面以一段C语言的代码为例,进行分析。
写C语言的程序,像一段八股文,有启承转合各个段落。
首先是程序文件的注释内容为程序功能的简要介绍,作者,版权信息。程序使用的注意事项
还有公开源代码的许可证信息,例如BSD许可,GNU GPL许可等。
然后是条件性编译的宏定义,包括真值定义为1,假值定义为0。还有最大值,最小值的
函数定义,它是采用宏定义的方式的标准写法。它的a和b的外面的多重括号,是为了防止
出现符号运行的优先级问题而写的。接下来是对调试符号的定义,这是典型的调试语句的
写法,在其它编程语言中,也可以仿照这一个写法。
然后是宏定义,包括文本的标题,文本的作者,文本的描述,文本的复制,文本的邮件地址
文本的统一资源地址。然后是它们的地址偏移量。
宏定义的原理是在C语言的编译器的预处理器对宏定义进行处理,它对源代码进行扫描,
把代码中遇到的宏的定义,替换成宏的实体。宏的作用有定义常量,定义函数。提高程序的
可阅读性,可维护性。
其次是程序的数据类型的自定义,相当于起别名。在C语言中数据类型例如整型,长整型等
要区别有符号还是无符号,这样的话,数据类型的名称分成几段,字符也较多。把它直接定义
在结构体的属性中,造成阅读不便,因此采用typedef这个自定义的关键字,还有一个原因是
在类unix的程序开发中,变量和数据类型之类的标识符的命名,希望是8个字符以内。这是
规范内容之一。
再其次是结构体的定义。这个程序只定义一个结构体,是主程序的信息的。
包括了宽度,高度,修改时间,输入文件,输出文件,PNG的指针,信息的指针
图像数据,行的指针,标题,作者,描述,版权,邮件地址,统一资源地址,
过滤器,pnm类型,采样深度,交织方法,背景,时间,文本,跳转的缓冲地址
背景的红通道,背景的绿通道,背景的蓝通道
最后是函数的定义包括
写文件的版本信息
写PNG的初始化
写PNG的编码的图像
写PNG的编码的行
写PNG的编码的结束
写PNG的清除
在函数的定义中,它们大都以结构体的指针为参数。
这是在其它的编程语言中,值得借鉴的。
源代码如下所示:
/*---------------------------------------------------------------------------
wpng - simple PNG-writing program writepng.h
---------------------------------------------------------------------------
Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
This software is provided "as is," without warranty of any kind,
express or implied. In no event shall the author or contributors
be held liable for any damages arising in any way from the use of
this software.
The contents of this file are DUAL-LICENSED. You may modify and/or
redistribute this software according to the terms of one of the
following two licenses (at your option):
LICENSE 1 ("BSD-like with advertising clause"):
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:
1. Redistributions of source code must retain the above copyright
notice, disclaimer, and this list of conditions.
2. Redistributions in binary form must reproduce the above copyright
notice, disclaimer, and this list of conditions in the documenta-
tion and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this
software must display the following acknowledgment:
This product includes software developed by Greg Roelofs
and contributors for the book, "PNG: The Definitive Guide,"
published by O'Reilly and Associates.
LICENSE 2 (GNU GPL v2 or later):
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
---------------------------------------------------------------------------*/
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
#ifndef MAX
# define MAX(a,b) ((a) > (b)? (a) : (b))
# define MIN(a,b) ((a) < (b)? (a) : (b))
#endif
#ifdef DEBUG
# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
#else
# define Trace(x) ;
#endif
#define TEXT_TITLE 0x01
#define TEXT_AUTHOR 0x02
#define TEXT_DESC 0x04
#define TEXT_COPY 0x08
#define TEXT_EMAIL 0x10
#define TEXT_URL 0x20
#define TEXT_TITLE_OFFSET 0
#define TEXT_AUTHOR_OFFSET 72
#define TEXT_COPY_OFFSET (2*72)
#define TEXT_EMAIL_OFFSET (3*72)
#define TEXT_URL_OFFSET (4*72)
#define TEXT_DESC_OFFSET (5*72)
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
typedef struct _mainprog_info {
double gamma;
long width;
long height;
time_t modtime;
FILE *infile;
FILE *outfile;
void *png_ptr;
void *info_ptr;
uch *image_data;
uch **row_pointers;
char *title;
char *author;
char *desc;
char *copyright;
char *email;
char *url;
int filter; /* command-line-filter flag, not PNG row filter! */
int pnmtype;
int sample_depth;
int interlaced;
int have_bg;
int have_time;
int have_text;
jmp_buf jmpbuf;
uch bg_red;
uch bg_green;
uch bg_blue;
} mainprog_info;
/* prototypes for public functions in writepng.c */
void writepng_version_info(void);
int writepng_init(mainprog_info *mainprog_ptr);
int writepng_encode_image(mainprog_info *mainprog_ptr);
int writepng_encode_row(mainprog_info *mainprog_ptr);
int writepng_encode_finish(mainprog_info *mainprog_ptr);
void writepng_cleanup(mainprog_info *mainprog_ptr);