[Mplayer-cvslog] CVS: 0_90/libmpcodecs vd_sgi.c,NONE,1.1 vd.c,1.65,1.66

Arpi of Ize arpi at mplayerhq.hu
Mon Mar 10 17:13:59 CET 2003


Update of /cvsroot/mplayer/0_90/libmpcodecs
In directory mail:/var/tmp.root/cvs-serv2510/libmpcodecs

Modified Files:
	vd.c 
Added Files:
	vd_sgi.c 
Log Message:
backport: sgi image decoding


--- NEW FILE ---
/*
 * author: Todd Kirby <slapcat at pacbell.net>
 */

#include <stdio.h>
#include <stdlib.h>

#include "config.h"
#include "mp_msg.h"
#include "bswap.h"
#include "vd_internal.h"

#define SGI_HEADER_LEN 512
#define SGI_MAGIC 474

#define SGI_GRAYSCALE_IMAGE 1
#define SGI_RGB_IMAGE 3
#define SGI_RGBA_IMAGE 4

#define OUT_PIXEL_STRIDE 3 /* RGB */


static vd_info_t info =
{
  "SGI Image decoder",
  "sgi",
  "Todd Kirby",
  "Todd Kirby",
  ""
};

LIBVD_EXTERN(sgi)

typedef struct {
  short magic;
  char rle;
  char bytes_per_channel;
  unsigned short dimension;
  unsigned short xsize;
  unsigned short ysize;
  unsigned short zsize;
} SGIInfo;

static unsigned int outfmt = IMGFMT_BGR24;

static unsigned short last_x = -1;
static unsigned short last_y = -1;


/* to set/get/query special features/parameters */
static int
control(sh_video_t* sh, int cmd, void *arg, ...)
{ 
  switch (cmd)
  {
    case VDCTRL_QUERY_FORMAT:
      if (*((unsigned int *) arg) == outfmt) {
        return CONTROL_TRUE;
      }
      return CONTROL_FALSE;
  }
  return CONTROL_UNKNOWN;
}


/* init driver */
static int
init(sh_video_t *sh)
{
  sh->context = (SGIInfo *) calloc(1, sizeof(SGIInfo));
  last_x = -1;

  return 1;
}


/* uninit driver */
static void
uninit(sh_video_t *sh)
{
  SGIInfo	*info = sh->context;
  free(info);
}


/* expand an rle row into a channel */
static void
expandrow(unsigned char *optr, unsigned char *iptr, int chan_offset)
{
  unsigned char pixel, count;
  optr += chan_offset;
  
  while (1) {
    pixel = *iptr++;
    
    if (!(count = (pixel & 0x7f))) {
      return;
    }
    if(pixel & 0x80) {
      while (count--) {
        *optr = *iptr;
        optr += OUT_PIXEL_STRIDE;
        iptr++;
      }
    } else {
      pixel = *iptr++;
      
      while (count--) {
        *optr = pixel;
        optr += OUT_PIXEL_STRIDE;
      }
    }
  }
}


/* expand an rle row into all 3 channels.
   a separate function for grayscale so we don't slow down the 
   more common case rgb function with a bunch of ifs. */
static void
expandrow_gs(unsigned char *optr, unsigned char *iptr)
{
  unsigned char pixel, count;
  
  while (1) {
    pixel = *iptr++;
    
    if (!(count = (pixel & 0x7f))) {
      return;
    }
    if(pixel & 0x80) {
      while (count--) {
        optr[0] = *iptr;
        optr[1] = *iptr;
        optr[2] = *iptr;
        optr += OUT_PIXEL_STRIDE;
        iptr++;
      }
    } else {
      pixel = *iptr++;
      
      while (count--) {
        optr[0] = pixel;
        optr[1] = pixel;
        optr[2] = pixel;
        optr += OUT_PIXEL_STRIDE;
      }
    }
  }
}


/* decode a run length encoded sgi image */
static void
decode_rle_sgi(SGIInfo *info, unsigned char *data, mp_image_t *mpi)
{
  unsigned char *rle_data, *dest_row;
  unsigned long *starttab;
  int y, z, xsize, ysize, zsize, chan_offset;
  long start_offset;
  
  xsize = info->xsize;
  ysize = info->ysize;
  zsize = info->zsize;

  /* rle offset table is right after the header */
  starttab = (long*)(data + SGI_HEADER_LEN); 
  
   for (z = 0; z < zsize; z++) {

     /* set chan_offset so RGB ends up BGR */
     chan_offset = (zsize - 1) - z;
     
     /* The origin for SGI images is the lower-left corner
        so read scan lines from bottom to top */
     for (y = ysize - 1; y >= 0; y--) {
       dest_row = mpi->planes[0] + mpi->stride[0] * (ysize - 1 - y);
    
      /* set start of next run (offsets are from start of header) */
      start_offset = be2me_32(*(unsigned long*) &starttab[y + z * ysize]);
      
      rle_data = &data[start_offset];
    
      if(info->zsize == SGI_GRAYSCALE_IMAGE) {
        expandrow_gs(dest_row, rle_data);
      } else {
        expandrow(dest_row, rle_data, chan_offset);
      }
    }
  }
}

  
/* decode an sgi image */
static void
decode_uncompressed_sgi(SGIInfo *info, unsigned char *data, mp_image_t *mpi)
{
  unsigned char *src_row, *dest_row;
  int x, y, z, xsize, ysize, zsize, chan_offset;
  
  xsize = info->xsize;
  ysize = info->ysize;
  zsize = info->zsize;
  
  /* skip header */ 
  data += SGI_HEADER_LEN;
  
  for (z = 0; z < zsize; z++) {

    /* set row ptr to start of current plane */
    src_row = data + (xsize * ysize * z);

    /* set chan_offset for RGB -> BGR */
    chan_offset = (zsize - 1) - z;
    
    /* the origin for SGI images is the lower-left corner  
       so read scan lines from bottom to top. */
    for (y = ysize - 1; y >= 0; y--) {
      dest_row = mpi->planes[0] + mpi->stride[0] * y;
      for (x = 0; x < xsize; x++) {
        
        /* we only do 24 bit output so promote 8 bit pixels to 24 */
        if (zsize == SGI_GRAYSCALE_IMAGE) {
          /* write greyscale value into all channels */
          dest_row[0] = src_row[x];
          dest_row[1] = src_row[x];
          dest_row[2] = src_row[x];
        } else {
          dest_row[chan_offset] = src_row[x];
        }
        
        dest_row += OUT_PIXEL_STRIDE;
      }

      /* move to next row of the current source plane */
      src_row += xsize;
    }
  }
}


/* read sgi header fields */
static void
read_sgi_header(unsigned char *buf, SGIInfo *info)
{
  /* sgi data is always stored in big endian byte order */
  info->magic = be2me_16(*(unsigned short *) &buf[0]);     
  info->rle = buf[2];
  info->bytes_per_channel = buf[3];
  info->dimension = be2me_16(*(unsigned short *) &buf[4]);     
  info->xsize = be2me_16(*(unsigned short *) &buf[6]);     
  info->ysize = be2me_16(*(unsigned short *) &buf[8]);     
  info->zsize = be2me_16(*(unsigned short *) &buf[10]);     
}


/* decode a frame */
static
mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags)
{
  SGIInfo *info = sh->context;
  unsigned char *data = raw;
  mp_image_t *mpi;

  if (len <= 0) {
    return NULL; /* skip frame */
  }
    
  read_sgi_header(data, info); 
  
  /* make sure this is an SGI image file */
  if (info->magic != SGI_MAGIC) {
    mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Bad magic number in image.\n");
    return NULL;
  }

  /* check image depth */
  if (info->bytes_per_channel != 1) {
    mp_msg(MSGT_DECVIDEO, MSGL_INFO, 
        "Unsupported bytes per channel value %i.\n", info->bytes_per_channel);
    return NULL;
  }

  /* check image dimension */
  if (info->dimension != 2 && info->dimension != 3) {
    mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported image dimension %i.\n", 
        info->dimension);
    return NULL;
  }

  /* change rgba images to rgb so alpha channel will be ignored */ 
  if (info->zsize == SGI_RGBA_IMAGE) {
    info->zsize = SGI_RGB_IMAGE;
  }

  /* check image depth */
  if (info->zsize != SGI_RGB_IMAGE && info->zsize != SGI_GRAYSCALE_IMAGE) {
    mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported image depth.\n");
    return NULL;
  }
  
  /* (re)init libvo if image size is changed */
  if (last_x != info->xsize || last_y != info->ysize)
  {
    last_x = info->xsize;
    last_y = info->ysize;
    
    if (!mpcodecs_config_vo(sh, info->xsize, info->ysize, outfmt)) {
      mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Config vo failed:\n");
      return NULL;
    }
  }
   
  if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, 
          info->xsize, info->ysize))) {
    return NULL;
  }
 
  if (info->rle) {
    decode_rle_sgi(info, data, mpi);
  } else {
    decode_uncompressed_sgi(info, data, mpi);
  }
  
  return mpi;
}


Index: vd.c
===================================================================
RCS file: /cvsroot/mplayer/0_90/libmpcodecs/vd.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -r1.65 -r1.66
--- vd.c	4 Feb 2003 17:50:30 -0000	1.65
+++ vd.c	10 Mar 2003 16:13:56 -0000	1.66
@@ -48,6 +48,7 @@
 extern vd_functions_t mpcodecs_vd_mpng;
 extern vd_functions_t mpcodecs_vd_ijpg;
 extern vd_functions_t mpcodecs_vd_mtga;
+extern vd_functions_t mpcodecs_vd_sgi;
 extern vd_functions_t mpcodecs_vd_libmpeg2;
 extern vd_functions_t mpcodecs_vd_huffyuv;
 extern vd_functions_t mpcodecs_vd_mpegpes;
@@ -100,6 +101,7 @@
 	&mpcodecs_vd_ijpg,
 #endif
 	&mpcodecs_vd_mtga,
+	&mpcodecs_vd_sgi,
 #ifdef USE_LIBMPEG2
         &mpcodecs_vd_libmpeg2,
 #endif
@@ -118,7 +120,7 @@
 	&mpcodecs_vd_libdv,
 #endif
 	&mpcodecs_vd_lcl,
-#ifdef USE_QTX_CODECS
+#if defined(USE_QTX_CODECS) || defined(MACOSX)
 	&mpcodecs_vd_qtvideo,
 #endif
 	NULL



More information about the MPlayer-cvslog mailing list