位 图 文 件 内 部 初 探
最 常 用 的 几 种 图 象 文 件 格 式 怎 样 存 储 图 象 自 从 我 在 十 四 年 前 买 回 第 一 台 pc 以 后, 我 就 一 直 对 计 算 机 用 1 和 0 组 成 的 数 据 流 来 存 储 那 些 复 杂 的 信 息 很 感 兴 趣。 最 初 引 起 我 注 意 的 是 当 时 曾 很 流 行 的 印 在 杂 志 上 的 basic 程 序 清 单, 它 们 带 有 很 多 数 据 段, 你 可 将 它 们 键 入 并 运 行, 以 建 立 其 他 的 程 序。 从 这 里 我 明 白 了 任 何 程 序 无 论 它 多 么 复 杂, 也 只 不 过 是 一 系 列 的 针 对 计 算 机 微 处 理 器 的 指 令 而 已。 接 着, 我 对 ascii 码 有 了 兴 趣, 然 后 是 字 处 理 文 件 格 式, 再 后 来 吗, 您 就 看 到 了 图 象。
直 至 今 天 仍 让 我 着 迷 的 一 种 技 术 是 位 图 文 件 存 储。 一 个 位 图 存 储 了 计 算 机 上 能 够 再 现 一 幅 图 象 所 需 的 信 息。 我 们 经 常 在 显 示 器 上 看 到 图 象, 例 如 一 幅 美 丽 的 日 落, 然 而 在 计 算 机 眼 里 它 只 是 一 堆 0 和 1 的 组 合。 归 根 结 底, 也 就 是 位 图 文 件 里 的 这 些 位 和 字 节 来 告 诉 计 算 机 这 幅 图 象 中 每 个 象 素 该 是 什 么 颜 色, 然 后 计 算 机 把 位 图 中 的 颜 色 转 化 成 与 它 的 显 示 卡 兼 容 的 格 式, 最 后 输 出 到 显 示 器 上。
这 个 过 程 中 有 趣 的 是 计 算 机 怎 样 解 释 位 图 中 的 数 据, 位 图 文 件 有 多 种 格 式, 每 种 格 式 都 有 自 己 的 方 法 对 象 素 数 据 编 码 并 给 出 此 种 格 式 所 要 求 的 一 些 其 他 信 息, 之 所 以 windows 95 能 够 读 取 .bmp 文 件 而 不 能 读 .gif 文 件, 就 是 因 为 他 的 设 计 人 员 使 paint 程 序 能 够 对 以 .bmp 格 式 存 储 的 图 象 数 据 进 行 解 码, 而 不 是 .gif。
到 这 里。 您 一 定 很 想 知 道 一 个 位 图 文 件 里 究 竟 是 什 么, 一 种 格 式 同 另 一 种 又 有 什 么 不 同 ? 那 么 就 让 我 们 来 简 单 地 看 看 在 pc 机 上 常 用 的 六 种 位 图 文 件 格 式。 当 然 还 有 其 他 的 文 件 格 式, 例 如 对 于 矢 量 图 形, 就 是 存 储 一 些 再 现 图 象 的 指 令 而 不 是 每 个 象 素 的 颜 色 数 据, 但 是 在 这 里 讨 论 的 这 六 种 位 图 文 件 格 式 才 是 您 平 时 工 作 最 可 能 使 用 的。
bmp 文 件
bmp(bitmap 的 缩 写) 文 件 格 式 是 windows 本 身 的 位 图 文 件 格 式, 所 谓 本 身 是 指 windows 内 部 存 储 位 图 即 采 用 这 种 格 式。 一 个 .bmp 格 式 的 文 件 通 常 有 .bmp 的 扩 展 名, 但 有 一 些 是 以 .rle 为 扩 展 名 的, rle 的 意 思 是 行 程 长 度 编 码(run length encoding)。 这 样 的 文 件 意 味 着 其 使 用 的 数 据 压 缩 方 法 是 .bmp 格 式 文 件 支 持 的 两 种 rle 方 法 中 的 一 种。
bmp 文 件 可 用 每 象 素 1、 4、 8、 16 或 24 位 来 编 码 颜 色 信 息, 这 个 位 数 称 作 图 象 的 颜 色 深 度, 它 决 定 了 图 象 所 含 的 最 大 颜 色 数。 一 幅 1-bpp(位 每 象 素, bit per pixel) 的 图 象 只 能 有 两 种 颜 色。 而 一 幅 24-bpp 的 图 象 可 以 有 超 过 16 兆 种 不 同 的 颜 色。
下 一 页 的 图 说 明 了 一 个 典 型 .bmp 文 件 的 结 构。 它 是 以 256 色 也 就 是 8-bpp 为 例 的, 文 件 被 分 成 四 个 主 要 的 部 分: 一 个 位 图 文 件 头, 一 个 位 图 信 息 头, 一 个 色 表 和 位 图 数 据 本 身。 位 图 文 件 头 包 含 关 于 这 个 文 件 的 信 息。 如 从 哪 里 开 始 是 位 图 数 据 的 定 位 信 息, 位 图 信 息 头 含 有 关 于 这 幅 图 象 的 信 息, 例 如 以 象 素 为 单 位 的 宽 度 和 高 度。 色 表 中 有 图 象 颜 色 的 rgb 值。 对 显 示 卡 来 说, 如 果 它 不 能 一 次 显 示 超 过 256 种 颜 色, 读 取 和 显 示 .bmp 文 件 的 程 序 能 够 把 这 些 rgb 值 转 换 到 显 示 卡 的 调 色 板 来 产 生 准 确 的 颜 色。
bmp 文 件 的 位 图 数 据 格 式 依 赖 于 编 码 每 个 象 素 颜 色 所 用 的 位 数。 对 于 一 个 256 色 的 图 象 来 说, 每 个 象 素 占 用 文 件 中 位 图 数 据 部 分 的 一 个 字 节。 象 素 的 值 不 是 rgb 颜 色 值, 而 是 文 件 中 色 表 的 一 个 索 引。 所 以 在 色 表 中 如 果 第 一 个 r/g/b 值 是 255/0/0, 那 么 象 素 值 为 0 表 示 它 是 鲜 红 色, 象 素 值 按 从 左 到 右 的 顺 序 存 储, 通 常 从 最 后 一 行 开 始。 所 以 在 一 个 256 色 的 文 件 中, 位 图 数 据 中 第 一 个 字 节 就 是 图 象 左 下 角 的 象 素 的 颜 色 索 引, 第 二 个 就 是 它 右 边 的 那 个 象 素 的 颜 色 索 引。 如 果 位 图 数 据 中 每 行 的 字 节 数 是 奇 数, 就 要 在 每 行 都 加 一 个 附 加 的 字 节 来 调 整 位 图 数 据 边 界 为 16 位 的 整 数 倍。
并 不 是 所 有 的 bmp 文 件 结 构 都 象 表 中 所 列 的 那 样, 例 如 16 和 24-bpp, 文 件 就 没 有 色 表, 象 素 值 直 接 表 示 rgb 值, 另 外 文 件 私 有 部 分 的 内 部 存 储 格 式 也 是 可 以 变 化 的。 例 如, 在 16 和 256 色 .bmp 文 件 中 的 位 图 数 据 采 用 rle 算 法 来 压 缩, 这 种 算 法 用 颜 色 加 象 素 个 数 来 取 代 一 串 颜 色 相 同 的 序 列, 而 且, windows 还 支 持 os/2 下 的 .bmp 文 件, 尽 管 它 使 用 了 不 同 的 位 图 信 息 头 和 色 表 格 式。
pcx 文 件
.pcx 是 在 pc 上 成 为 位 图 文 件 存 储 标 准 的 第 一 种 图 象 文 件 格 式。 它 最 早 出 现 在 zsoft 公 司 的 paintbrush 软 件 包 中, 在 80 年 代 早 期 授 权 给 微 软 与 其 产 品 捆 绑 发 行, 而 后 转 变 为 microsoft paintbrush, 并 成 为 windows 的 一 部 分。 虽 然 使 用 这 种 格 式 的 人 在 减 少, 但 这 种 带 有 .pcx 扩 展 名 的 文 件 在 今 天 仍 是 十 分 常 见 的。
pcx 文 件 分 为 三 部 分, 依 次 为: pcx 文 件 头, 位 图 数 据 和 一 个 可 选 的 色 表。 文 件 头 长 达 128 个 字 节, 分 为 几 个 域, 包 括 图 象 的 尺 寸 和 每 个 象 素 颜 色 的 编 码 位 数。 位 图 数 据 用 一 种 简 单 的 rle 算 法 压 缩, 最 后 的 可 选 色 表 有 256 个 rgb 值, pcx 格 式 最 初 是 为 cga 和 ega 来 设 计 的, 后 来 经 过 修 改 也 支 持 vga 和 真 彩 色 显 示 卡, 现 在 pcx 图 象 可 以 用 1、 4、 8 或 24-bpp 来 对 颜 色 数 据 进 行 编 码。
tiff 文 件
pcx 格 式 是 所 有 位 图 文 件 格 式 中 最 简 单 的, 而 tiff(tagged image file format) 则 是 最 难 的 一 种。
tiff 文 件 含 有 .tif 的 扩 展 名。 它 以 8 字 节 长 的 图 象 文 件 头 开 始 (ifh), 这 个 文 件 头 中 最 重 要 的 成 员 是 一 个 指 向 名 为 图 象 文 件 目 录 (ifd) 的 数 据 结 构 的 指 针。 ifd 是 一 个 名 为 标 记(tag) 的 用 于 区 分 一 个 或 多 个 可 变 长 度 数 据 块 的 表, 标 记 中 含 有 关 于 图 象 的 信 息。 tiff 文 件 格 式 定 义 70 多 种 不 同 类 型 的 标 记, 有 的 用 来 存 放 以 象 素 为 单 位 的 图 象 宽 度 和 高 度, 有 的 用 来 存 放 色 表 ( 如 果 需 要 的 话 ), 当 然 还 必 须 有 用 来 存 放 位 图 数 据 的 标 记, 一 个 tiff 格 式 文 件 完 全 为 它 的 标 记 所 决 定, 而 且 这 种 文 件 结 构 极 易 扩 展, 因 为 你 要 附 加 一 些 特 征 只 须 增 加 一 些 额 外 的 标 记。
究 竟 是 什 么 使 tiff 文 件 如 此 复 杂? 一 方 面, 要 写 一 种 能 够 识 别 所 用 不 同 标 记 的 软 件 非 常 困 难。 大 多 数 tiff 的 阅 读 程 序 只 能 识 别 一 部 分 标 记, 所 以 会 出 现 这 种 情 况: 有 时 一 个 应 用 程 序 创 建 的 tiff 文 件, 另 一 个 应 用 程 序 却 不 能 使 用。 创 建 tiff 文 件 的 程 序 还 可 能 会 在 文 件 中 加 一 些 只 有 它 自 己 认 识 的 标 记, 虽 然 tiff 的 阅 读 程 序 可 以 跳 过 那 些 它 们 不 认 得 的 标 记, 但 这 样 做 总 是 有 可 能 影 响 到 图 象 的 质 量。
另 一 方 面, 一 个 tiff 文 件 可 以 包 含 多 个 图 象, 每 个 图 象 都 有 自 己 的 ifd 和 一 系 列 标 记。 tiff 文 件 中 的 位 图 数 据 可 能 会 用 好 几 种 方 法 来 压 缩, 所 以 一 个 完 备 的 tiff 阅 读 程 序 应 该 有 rle 解 压 缩 程 序, lzw 解 压 缩 程 序 和 其 他 一 些 算 法 的 解 压 缩 程 序。 然 而 更 糟 的 是 使 用 lzw 的 解 码 必 须 得 到 unisys 公 司 的 同 意, 且 通 常 是 需 要 付 版 税 的。 所 以 即 使 是 一 些 相 当 不 错 的 tiff 阅 读 程 序 在 它 们 遇 到 lzw 算 法 压 缩 的 图 象 时 也 是 无 能 为 力 的。
尽 管 tiff 是 那 么 的 复 杂, 但 仍 是 一 种 最 好 的 跨 平 台 格 式。 因 为 它 非 常 灵 活, 无 论 在 视 觉 上 还 是 其 他 方 面, 都 能 把 任 何 图 象 编 码 成 二 进 制 形 式 而 不 丢 失 任 何 属 性。
gif 文 件
当 许 多 图 象 方 面 的 权 威 一 想 到 lzw 的 时 候, 他 们 也 会 想 到 gif(graphics interchange format, 读 作 jiff) 这 是 一 种 常 用 的 跨 平 台 的 位 图 文 件 格 式, 最 初 为 compuserve 公 司 所 创。 gif 文 件 通 常 带 有 .gif 的 扩 展 名, 而 且 在 compuseve 上 大 量 存 在。
gif 文 件 的 结 构 取 决 于 它 属 于 哪 一 个 版 本, 目 前 的 两 种 版 本 分 别 是 gif87a 和 gif89a, 前 者 较 简 单。 无 论 是 哪 个 版 本, 它 都 以 一 个 长 13 字 节 的 文 件 头 开 始, 文 件 头 中 包 含 判 定 此 文 件 是 gif 文 件 的 标 记、 版 本 号 和 其 他 的 一 些 信 息。 如 果 这 个 文 件 只 有 一 幅 图 象, 文 件 头 后 紧 跟 一 个 全 局 色 表 来 定 义 图 象 中 的 颜 色。 如 果 含 有 多 幅 图 象 (gif 和 tiff 格 式 一 样, 允 许 在 一 个 文 件 里 编 码 多 个 图 象 ), 那 么 全 局 色 表 就 被 各 个 图 象 自 带 的 局 部 色 表 所 替 代。
在 gif87a 文 件 中, 文 件 头 和 全 局 色 表 之 后 是 图 象, 它 可 能 会 是 头 尾 相 接 的 一 串 图 象 中 的 第 一 个, 每 个 图 象 由 三 部 分 组 成, 一 个 10 字 节 长 的 图 象 描 述, 一 个 可 选 的 局 部 色 表 和 位 图 数 据。 为 有 效 利 用 空 间, 位 图 数 据 用 lzw 算 法 来 压 缩。
gif89a 结 构 与 此 类 似, 但 它 还 包 括 可 选 的 扩 展 块 来 存 放 每 个 图 象 的 附 加 信 息。 gif89a 详 细 定 义 了 四 种 扩 展 块: 图 象 控 制 扩 展 块, 它 用 来 描 述 图 象 怎 样 被 显 示 ( 例 如, 显 示 是 应 该 象 一 个 透 明 物 去 覆 盖 上 一 个 图 象, 还 是 简 单 的 替 换 它 ); 简 单 文 本 扩 展 块, 它 包 含 显 示 在 图 象 中 的 文 本; 注 释 扩 展 块, 它 以 ascii 文 本 形 式 存 放 注 释 ; 应 用 扩 展 块, 它 存 放 生 成 该 文 件 的 应 用 程 序 的 私 有 数 据。 这 些 扩 展 块 可 以 出 现 在 文 件 中 全 局 色 表 的 任 何 地 方。
gif 最 显 著 的 优 点 是 它 的 广 泛 使 用 和 它 的 紧 密 性。 但 它 有 两 个 弱 点, 一 个 是 用 gif 格 式 存 放 的 文 件 最 多 只 能 含 有 256 种 颜 色。 另 一 个 可 能 更 重 要, 就 是 那 些 使 用 了 gif 格 式 的 软 件 开 发 者 必 须 征 得 compuserve 的 同 意, 他 们 每 卖 出 一 个 拷 贝 都 要 向 compuserve 付 版 税。 这 个 政 策 是 compuserve 仿 效 unisys 公 司 作 出 的, 它 抑 制 了 那 些 程 序 员 在 他 的 图 象 应 用 程 序 中 支 持 gif 文 件。
png 文 件
png(portable network graphic, 发 音 做 ping) 文 件 格 式 是 作 为 gif 的 替 代 品 开 发 的, 它 能 够 避 免 使 用 gif 文 件 所 遇 到 的 常 见 问 题。 它 从 gif 那 里 继 承 了 许 多 特 征, 而 且 支 持 真 彩 色 图 象。 更 重 要 的 是, 在 压 缩 位 图 数 据 时 它 采 用 了 一 种 颇 受 好 评 的 lz77 算 法 的 一 个 变 种, lz77 则 是 lzw 的 前 身, 而 且 可 以 免 费 使 用。 由 于 篇 幅 所 限, 在 这 里 就 不 花 时 间 来 具 体 讨 论 png 格 式 了。
jpeg 文 件
jpeg(joint photographic experts group, 发 音 做 jay-peg) 文 件 格 式 最 初 由 c-cube microsystems 推 出, 是 为 了 提 供 一 种 存 储 深 度 位 象 素 的 有 效 方 法, 例 如 对 于 照 片 扫 描, 颜 色 很 多 而 且 差 别 细 微 ( 有 时 也 不 细 微 )。 jpeg 和 这 里 讨 论 的 其 他 格 式 的 最 大 区 别 是 jpeg 使 用 一 种 有 损 压 缩 算 法, 无 损 压 缩 算 法 能 在 解 压 后 准 确 再 现 压 缩 前 的 图 象, 而 有 损 压 缩 则 牺 牲 了 一 部 分 的 图 象 数 据 来 达 到 较 高 的 压 缩 率。 但 是 这 种 损 失 很 小 以 至 于 人 们 很 难 察 觉。
jpeg 图 象 压 缩 是 一 个 复 杂 的 过 程, 经 常 需 要 专 门 的 硬 件 来 帮 助。 首 先 图 象 以 象 素 为 单 位 分 成 8*8 的 块。 然 后, 每 个 块 分 三 个 步 骤 被 压 缩。 第 一 步 使 用 dct(discrete cosine transform) 离 散 余 弦 变 换 把 8*8 的 象 素 矩 阵 变 成 8*8 的 频 率(也 就 是 颜 色 改 变 的 速 度) 矩 阵。 第 二 步 对 频 率 矩 阵 中 的 值 用 量 化 矩 阵 进 行 量 化, 滤 掉 那 些 总 体 上 对 图 象 不 重 要 的 部 分。 第 三 步, 也 就 是 最 后 一 步, 对 量 化 后 的 频 率 矩 阵 使 用 无 损 压 缩。
因 为 被 量 化 后 的 频 率 矩 阵 缺 了 许 多 高 频 信 息, 通 常 能 被 压 缩 到 一 半 甚 至 更 少。 无 损 压 缩 一 般 根 本 不 能 压 缩 真 正 的 照 片 图 象, 所 以 50% 的 压 缩 率 已 是 相 当 不 错 了, 但 另 一 方 面, 无 损 压 缩 能 把 一 些 图 象 文 件 尺 寸 减 少 90%, 这 样 的 图 象 文 件 就 不 适 合 用 jpeg 来 压 缩。
jpeg 的 有 损 部 分 产 生 在 第 二 步, 量 化 矩 阵 的 值 越 高, 从 图 象 中 丢 掉 的 信 息 就 越 多, 从 而 压 缩 率 就 越 高, 可 是 同 时 图 象 的 质 量 就 越 差。 在 jpeg 压 缩 时 可 以 选 择 一 个 量 化 因 子, 这 个 因 子 的 值 决 定 了 量 化 矩 阵 中 的 数 值。 理 想 的 量 化 因 子 要 在 压 缩 率 和 图 象 质 量 间 达 到 平 衡, 所 以 对 不 同 的 图 象 要 选 择 不 同 的 量 化 因 子, 通 常 要 经 过 若 干 次 尝 试 后 方 可 确 定。