Next: Compression Up: Image Previous: Dithering

Encoding

Rasterfile Format

Rasterfile Structure

struct rasterfile {
        int     ras_magic;              /* magic number */
        int     ras_width;              /* width (pixels) of image */
        int     ras_height;             /* height (pixels) of image */
        int     ras_depth;              /* depth (1, 8, or 24 bits) of pixel */
        int     ras_length;             /* length (bytes) of image */
        int     ras_type;               /* type of file; see RT_* below */
        int     ras_maptype;            /* type of colormap; see RMT_* below */
        int     ras_maplength;          /* length (bytes) of following map */
};

#define RAS_MAGIC       0x59a66a95

#define RT_OLD          0       /* Raw pixrect image in 68000 byte order */
#define RT_STANDARD     1       /* Raw pixrect image in 68000 byte order */
#define RT_BYTE_ENCODED 2       /* Run-length compression of bytes */
#define RT_FORMAT_RGB   3       /* XRGB or RGB instead of XBGR or BGR */

#define RMT_NONE        0       /* ras_maplength is expected to be 0 */
#define RMT_EQUAL_RGB   1

Generating the Header

static void ras_header(struct rasterfile *h, Image *i, int cflag)
{
  h->ras_magic = RAS_MAGIC;
  h->ras_width = i->w;
  h->ras_height = i->h;
  h->ras_depth = (img_type(i) == IMG_TRUECOL)? 24 : 8;
  h->ras_length = i->w * i->h;
  h->ras_type = (cflag)? RT_SIMPLE_RLE : RT_STANDARD;
  h->ras_maptype = (img_type(i) == IMG_MAPPCOL)? RMT_EQUAL_RGB : RMT_NONE;
  h->ras_maplength = (img_type(i) == IMG_MAPPCOL)? sizeof(CMap) : 0;
}

Raw Encoding

Writing an Image

}void img_write(Image *i, char *fname, int cflag)
{
  struct rasterfile h;
  int fd;

  fd = (strcmp("stdout", fname) == 0)? 1 : ecreat(fname, 0666);

  ras_header(&h, i, cflag);
  write_sunheader(fd, &h);

  if (img_type(i) == IMG_MAPPCOL && i->m != NULL)
    write(fd, i->m, sizeof(CMap));

  switch (h.ras_type) {
  case RT_FORMAT_RGB:
    sunras_write(fd, h.ras_depth, i->w, i->h, i->u.c); break;
  case RT_STANDARD: 
    sunras_write(fd, h.ras_depth, i->w, i->h, i->u.b); break;
  case RT_SIMPLE_RLE: 
    rle_write(fd, i); break;
  }
  close(fd);
}

Reading an Image

Image *img_read(char *fname)
{
  struct rasterfile h;
  int fd;
  Image *i;
  
  fd =  (strcmp("stdin", fname) == 0)? 0 : eopen(fname, 0);
  read_sunheader(fd, &h);
  if (h.ras_magic != RAS_MAGIC)
    error("(img_read) wrong format");
  i = img_init(IMG_RASTYPE(h), h.ras_width, h.ras_height);

  if (h.ras_maptype == RMT_EQUAL_RGB)
    cmap_read(i->m, h.ras_maplength, fd);

  switch (h.ras_type) {
  case RT_FORMAT_RGB:
    sunras_read(fd, h.ras_depth, i->w, i->h, i->u.c); break;
  case RT_STANDARD: 
    sunras_read(fd, h.ras_depth, i->w, i->h, i->u.b); break;
  case RT_SIMPLE_RLE:
    rle_read(fd, i); break;
  default: 
    error("(img_read) unknown format");
  }
  close(fd);
  return i;
}

Machine Independent I/O

static void read_sunheader(int fd, struct rasterfile *h)
{
  read_sun_long(&(h->ras_magic), fd);
  read_sun_long(&(h->ras_width), fd);
  read_sun_long(&(h->ras_height), fd);
  read_sun_long(&(h->ras_depth), fd);
  read_sun_long(&(h->ras_length), fd);
  read_sun_long(&(h->ras_type), fd);
  read_sun_long(&(h->ras_maptype), fd);
  read_sun_long(&(h->ras_maplength), fd);
}

static void read_sun_long(int *l, int fd)
{
  unsigned char c0, c1, c2, c3;

  read(fd,&c0,1); read(fd,&c1,1); read(fd,&c2,1); read(fd,&c3,1);

  *l = (((unsigned int) c0 & 0xff) << 24) |
       (((unsigned int) c1 & 0xff) << 16) |
       (((unsigned int) c2 & 0xff) <<  8) |
       (((unsigned int) c3 & 0xff));
}

static void write_sun_long(unsigned int l, int fd)
{
    unsigned char c;
    c = ((l >> 24) & 0xff); write(fd, &c, 1);
    c = ((l >> 16) & 0xff); write(fd, &c, 1);
    c = ((l >> 8) & 0xff); write(fd, &c, 1);
    c = (l & 0xff); write(fd, &c, 1);
}

static void sunras_read(int fd, int d, int w, int h, void *buf)
{
  int i, lsize, padline;
  char pad[1], *bp;

  lsize = (w * d)/8;
  padline = ((w * d) % 16)? TRUE : FALSE;
  for (i = 0, bp = buf; i < h; i++, bp += lsize) {
    read(fd, bp, lsize);
    if (padline) read(fd, &pad, 1);
  }
}

static void sunras_write(int fd, int d, int w, int h, void *buf)
{
  int i, lsize, padline;
  char pad[1], *bp;

  lsize = (w * d)/8;
  padline = ((w * d) % 16)? TRUE : FALSE;
  for (i = 0, bp = buf; i < h; i++, bp += lsize) {
    write(fd, bp, lsize);
    if (padline) write(fd, &pad, 1);
  }
}



Luiz Velho
Wed Apr 7 12:17:01 "EST 1999