概述
介绍
这是描述SGI图像文件格式的权威文档。这是一个低级规范,描述了 SGI 图像文件的实际字节级格式。在 SGI 机器上,读取和写入 SGI 图像文件的首选方法是使用图像库 -limage。此库提供了一组函数,使读取和写入 SGI 图像变得容易。如果您使用的是 SGI 工作站,您可以通过以下方式获取有关 -limage 的信息:
% man 4 rgb
关于 SGI 图像文件中值的字节顺序的说明
在下面的描述中,像 bits[7..0] 这样的表示法用于表示二进制值中的位范围。位 0 是值中的最低位。
所有短值均由 2 个字节表示。第一个字节存储高阶 8 位的值:bits[15..8]。第二个字节存储值的低阶 8 位:bits[7..0]。
因此,此函数将从文件中读取一个短值:
unsigned short getshort(inf)
FILE *inf;
{
unsigned char buf[2];
fread(buf,2,1,inf);
return (buf[0]<<8)+(buf[1]<<0);
}
所有长值都由 4 个字节表示。第一个字节存储高阶 8 位的值:bits[31..24]。第二个字节存储位[23..16]。第三个字节存储位[15..8]。第四个字节存储值的低阶 8 位:bits[7..0]。
此函数将从文件中读取一个长值:
static long getlong(inf)
FILE *inf;
{
unsigned char buf[4];
fread(buf,4,1,inf);
return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
}
SGI 图像文件的一般结构
标头指示图像是否为运行长度编码 (RLE)。
如果图像未进行运行长度编码,则结构如下:
The Header
The Image Data
如果图像是运行长度编码的,则结构如下:
The Header
The Offset Tables
The Image Data
页眉
标头包含以下内容:
Size | Type | Name | Description
2 bytes | short | MAGIC | IRIS image file magic number
1 byte | char | STORAGE | Storage format
1 byte | char | BPC | Number of bytes per pixel channel
2 bytes | ushort | DIMENSION | Number of dimensions
2 bytes | ushort | XSIZE | X size in pixels
2 bytes | ushort | YSIZE | Y size in pixels
2 bytes | ushort | ZSIZE | Number of channels
4 bytes | long | PIXMIN | Minimum pixel value
4 bytes | long | PIXMAX | Maximum pixel value
4 bytes | char | DUMMY | Ignored
80 bytes | char | IMAGENAME | Image name
4 bytes | long | COLORMAP | Colormap ID
404 bytes | char | DUMMY | Ignored
以下是图像文件头中每个字段的说明:
魔术 - 这是保存为短整型的十进制值 474。这会将文件标识为 SGI 映像文件。
存储 - 指定是否使用运行长度编码 (RLE) 或不使用 (逐字) 存储图像。如果使用 RLE,则此字节的值将为 1。否则,此字节的值将为 0。此字段唯一允许的值为 0 或 1。
BPC - 描述用于存储图像的每个通道的精度。这是每个像素分量的字节数。大多数 SGI 图像文件使用每像素 1 个字节的分量,给出 256 个级别。某些 SGI 映像文件每个组件使用 2 个字节。此字段唯一允许的值为 1 或 2。
维度 - 描述存储在图像文件中的数据中的维度数。唯一允许的值为 1、2 或 3。如果此值为 1,则图像文件仅包含 1 个通道和 1 条扫描线(行)。此扫描线的长度由下面的 XSIZE 值给出。如果此值为 2,则文件由具有多个扫描线的单个通道组成。图像的宽度和高度由下面的 XSIZE 和 YSIZE 值给出。如果此值为 3,则文件由多个通道组成。图像的宽度和高度由下面的 XSIZE 和 YSIZE 值给出。通道数由下面的 ZSIZE 值给出。
XSIZE - 图像的宽度(以像素为单位)
YSIZE - 图像的高度(以像素为单位)
ZSIZE - 图像中的通道数。黑白(灰度)图像存储为 ZSIZE 或 1 的二维图像。RGB 彩色图像存储为 ZSIZE 为 3 的三维图像。具有 ALPHA 通道的 RGB 图像存储为 ZSIZE 为 4 的三维图像。SGI图像文件格式并无固有限制,无法创建超过4个通道的图像文件。
PINMIN - 图像中的最小像素值。如果没有像素的值小于 0,则可以使用 0 的值。
PINMAX - 图像中的最大像素值。如果没有像素的值大于 255,则可以使用 255 的值。这是图像中被视为全亮度的值。
虚拟 - 这 4 个字节的数据应设置为 0。
图像名称 - 此处可能包含以空结尾的 ASCII 字符串,该字符串最多包含 79 个字符,以空结尾。这不常用。
颜色映射表 - 这控制应如何解释文件中的像素值。它可以具有以下四个值之一:
0:正常 - 通道中的数据表示具有 1 个通道的图像的黑白值、具有 3 个通道的图像的 RGB 值和具有 4 个通道的图像的 RGBA 值。几乎所有的SGI图像文件都是这种类型的。
1:抖动 - 图像将只有 1 个数据通道。对于每个像素,RGB 数据被打包到一个 8 位值中。3 位用于红色和绿色,而蓝色使用 2 位。红色数据以位[2..0]为单位,绿色数据以位[5..3]为单位,蓝色数据以位[7..6]为单位。此格式已过时。
2:屏幕 - 图像将只有 1 个数据通道。此格式用于存储颜色索引像素。要将像素值转换为 RGB 值,必须使用颜色图。适当的颜色映射因图像而异。此格式已过时。
3:颜色图 - 图像用于存储来自SGI机器的色彩映射。在这种情况下,图像在传统意义上不可显示。
虚拟 - 此 404 字节的数据应设置为 0。这使得标头正好为 512 字节。
图像数据(如果不是 RLE)
如果图像是逐字存储的(没有 RLE),则图像数据直接跟在 512 字节标头之后。首先写入第一个通道的每个扫描线的数据。如果映像具有 1 个以上的通道,则写入第一个通道的所有数据,然后写入其余通道。如果 BPC 值为 1,则每个扫描线都写入为 XSIZE 字节。如果 BPC 值为 2,则每条扫描线都写为 XSIZE 短裤。这些短裤按上述字节顺序存储。
偏移表(如果是 RLE)
如果使用运行长度编码存储图像,则偏移表跟在标题后面,该标头描述了每个扫描线的文件偏移量对 RLE 的偏移量。仅当上述存储的值为 1 时,此信息才适用。
Size | Type | Name | Description
tablen longs | long | STARTTAB | Start table
tablen longs | long | LENGTHTAB | Length table
RLE 数据的每个扫描行都需要每个表中的一个条目。图像(表n)中的扫描线总数由YSIZE和ZSIZE的乘积决定。写了两个长头表。每个都由表长的数据组成。第一个表具有图像中每条扫描线的 RLE 数据的文件偏移量。在具有 1 个以上通道(ZSIZE > 1)的文件中,此表首先包含第一个通道中扫描线的所有偏移量,然后是第二个通道中扫描线的偏移量,依此类推。第二个表包含图像中每条扫描线的 RLE 数据长度。在具有 1 个以上通道(ZSIZE > 1)的文件中,此表首先包含第一个通道中扫描线的所有 RLE 数据长度,然后是第二个通道中扫描线的 RLE 数据长度,依此类推。
要查找文件偏移量以及特定扫描线的 RLE 数据中的字节数,可以按如下方式读取这两个数组并编制索引:
要在表格中阅读:
unsigned long *starttab, *lengthtab;
tablen = YSIZE*ZSIZE*sizeof(long);
starttab = (unsigned long *)mymalloc(tablen);
lengthtab = (unsigned long *)mymalloc(tablen);
fseek(inf,512,SEEK_SET);
readlongtab(inf,starttab);
readlongtab(ing,lengthtab);
要查找扫描线的文件偏移量和 RLE 数据长度:
rowno 是 0 到 YSIZE-1 范围内的整数 channo 是 0 到 ZSIZE-1 范围内的整数
rleoffset = starttab[rowno+channo*YSIZE]
rlelength = lengthtab[rowno+channo*YSIZE]
两个相同的行(扫描线)可以共享压缩数据。可以将完全白色的图像写入单个压缩行,并使所有表条目都指向该行。另一个应该有效的小技巧是,如果您正在写出RGB RLE文件,并且特定的扫描线是消色差的(灰度),则可以使r,g和b行指向相同的数据!
图像数据(如果是 RLE)
仅当上述存储的值为 1 时,此信息才适用。如果使用运行长度编码存储图像,则图像数据遵循上面的偏移表。RLE 数据不按任何特定顺序排列。上面的偏移表用于定位任何扫描线的 rle 数据。
必须按以下方式从文件中读入 RLE 数据并将其扩展为像素数据:
如果 BPC 为 1,则每个像素有一个字节。在这种情况下,应将 RLE 数据读入字符数组。为了扩展数据,第一个字节的低阶七位:bits[6..0]用于形成计数。如果第一个字节的高阶位为 1: bit[7],则计数用于指定要从 RLE 数据缓冲区复制到目标的字节数。否则,如果第一个字节的高阶位为 0: bit[7],则计数用于指定在目标中重复下一个字节的值的次数。此过程一直持续到找到计数 0。这应该完全解压缩 XSIZE 像素。
以下是解压缩扫描线的示例代码:
expandrow(optr,iptr,z)
unsigned char *optr, *iptr;
int z;
{
unsigned char pixel, count;
optr += z;
while(1) {
pixel = *iptr++;
if ( !(count = (pixel & 0x7f)) )
return;
if(pixel & 0x80) {
while(count--)
*optr++ = *iptr++;
} else {
pixel = *iptr++;
while(count--)
*optr++ = pixel;
}
}
}
如果 BPC 为 2,则每个像素有一个短(2 个字节)。在这种情况下,RLE 数据应读入短路数组。为了扩展数据,使用第一个短:bits[6..0]的低阶七位来形成计数。如果第一个短路的 bit[7] 为 1,则计数用于指定要从 RLE 数据缓冲区复制到目标的短路数。否则,如果第一个短裤的 bit[7] 为 0,则计数用于指定在目标中重复下一个短指令的值的次数。此过程将继续,直到找到计数 0。这应该完全解压缩 XSIZE 像素。请注意,应使用输入文件中短数据的字节顺序,如上所述。
实施说明
对于 BPC 为 1 的图像,需要同时实现 RLE 和 VERBATIM 格式,因为绝大多数 SGI 图像都是这种格式。鼓励支持具有 2 BPC 的图像。
如果图像的 ZSIZE 为 1,则假定它表示黑白值。如果 ZSIZE 为 3,则假定它表示 RGB 数据,如果 ZSIZE 为 4,则假定它包含带有 alpha 的 RGB 数据。
所有SGI图像的原点都是左下角。第一条扫描线(第 0 行)始终是图像的底行。
命名约定
在 SGI 系统上,如果 SGI 图像文件是黑白图像,则以扩展名 .bw 结尾,如果包含 RGB 图像数据,则以 .rgb 结尾,如果是带有 alpha 通道的 RGB 图像,则以 .rgba 结尾。
有时也会使用.sgi扩展名。
一个例子
此程序将写出有效的黑白SGI映像文件:
#include "stdio.h"
#define IXSIZE (23)
#define IYSIZE (15)
putbyte(outf,val)
FILE *outf;
unsigned char val;
{
unsigned char buf[1];
buf[0] = val;
fwrite(buf,1,1,outf);
}
putshort(outf,val)
FILE *outf;
unsigned short val;
{
unsigned char buf[2];
buf[0] = (val>>8);
buf[1] = (val>>0);
fwrite(buf,2,1,outf);
}
static int putlong(outf,val)
FILE *outf;
unsigned long val;
{
unsigned char buf[4];
buf[0] = (val>>24);
buf[1] = (val>>16);
buf[2] = (val>>8);
buf[3] = (val>>0);
return fwrite(buf,4,1,outf);
}
main()
{
FILE *of;
char iname[80];
unsigned char outbuf[IXSIZE];
int i, x, y;
of = fopen("example.rgb","w");
if(!of) {
fprintf(stderr,"sgiimage: can't open output filen");
exit(1);
}
putshort(of,474); /* MAGIC */
putbyte(of,0); /* STORAGE is VERBATIM */
putbyte(of,1); /* BPC is 1 */
putshort(of,2); /* DIMENSION is 2 */
putshort(of,IXSIZE); /* XSIZE */
putshort(of,IYSIZE); /* YSIZE */
putshort(of,1); /* ZSIZE */
putlong(of,0); /* PIXMIN is 0 */
putlong(of,255); /* PIXMAX is 255 */
for(i=0; i<4; i++) /* DUMMY 4 bytes */
putbyte(of,0);
strcpy(iname,"No Name");
fwrite(iname,80,1,of); /* IMAGENAME */
putlong(of,0); /* COLORMAP is 0 */
for(i=0; i<404; i++) /* DUMMY 404 bytes */
putbyte(of,0);
for(y=0; y<IYSIZE; y++) {
for(x=0; x<IXSIZE; x++)
outbuf[x] = (255*x)/(IXSIZE-1);
fwrite(outbuf,IXSIZE,1,of);
}
fclose(of);
}
最后
以上就是暴躁金毛为你收集整理的SGI图像文件格式的全部内容,希望文章能够帮你解决SGI图像文件格式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复