home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / video / simpleVideo / lib / svImage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  13.0 KB  |  522 lines

  1. /*
  2.  * Copyright (c) 1994, Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  */
  20. /* $Id: svImage.c,v 1.4 1994/04/28 22:06:06 dpb Exp $ */
  21.  
  22. #include <fcntl.h>
  23. #include <unistd.h>
  24. #include <stdlib.h>
  25. #include <sys/stat.h>
  26. #include <sys/wait.h>
  27. #include <gl/gl.h>
  28. #define iopen junk1 
  29. #include <gl/image.h>
  30. #undef iopen
  31.  
  32. #include "vlUtil.h"
  33. #include "sv.h"
  34. #include "svPriv.h"
  35.  
  36. /********************************************************/
  37. /*** XXX why aren't these in image.h for real?        ***/
  38. /*** End of prototypes that should be in <gl/image.h> ***/
  39. /********************************************************/
  40.  
  41. int putrow(IMAGE *image,
  42.        unsigned short *buffer,
  43.        int y,
  44.        int z);
  45.  
  46. int getrow(IMAGE *image,
  47.        unsigned short *buffer,
  48.        int y,
  49.        int z);
  50.  
  51. IMAGE *iopen(char *file,
  52.          char *mode,
  53.          ...);
  54.  
  55. int iclose (IMAGE *);
  56.  
  57. /********************************************************/
  58. /*** End of prototypes that should be in <gl/image.h> ***/
  59. /********************************************************/
  60.  
  61.  
  62. /***
  63.  *** Forward declaration of local static functions;
  64.  ***/
  65.  
  66. static unsigned long *
  67. longimagedata(char *name);
  68.  
  69. typedef unsigned long ul;
  70.  
  71.  
  72. /**********************************************************************
  73.  *  
  74.  * svNewImage - 
  75.  *
  76.  * Allocate and initialize a svImage record;
  77.  **********************************************************************
  78.  */
  79. svImage *
  80. svNewImage(void)
  81. {
  82.     svImage *frame;
  83.  
  84.     frame = malloc(sizeof(svImage));
  85.     if (frame) {
  86.     frame->width = 0;
  87.     frame->height = 0;
  88.     frame->packing = -1;
  89.     frame->dataMalloced = FALSE;
  90.     frame->data = NULL;
  91.     frame->compressed = FALSE;
  92.     }
  93.  
  94.     return frame;
  95. }
  96.  
  97. /**********************************************************************
  98.  *
  99.  * svFreeImage -
  100.  *
  101.  * Free an image data structure;
  102.  **********************************************************************
  103.  */
  104.  
  105. void
  106. svFreeImage(svImage **userFrame)
  107. {
  108.     svImage *frame;
  109.  
  110.     frame = *userFrame;
  111.  
  112.     if (frame->dataMalloced)
  113.     free(frame->data);
  114.     frame->data = NULL;
  115.  
  116.     free(frame);
  117.     *userFrame = NULL;
  118. }
  119.  
  120. /**********************************************************************
  121.  *  
  122.  * svSaveImage - 
  123.  *
  124.  * Save an image to a file
  125.  **********************************************************************
  126.  */
  127. int
  128. svSaveImage(char *filename, svImage *frame)
  129. {
  130.     IMAGE *image;
  131.     ushort rbuf[1024];
  132.     ushort gbuf[1024];
  133.     ushort bbuf[1024];
  134.     int x, y;
  135.  
  136.     char *data;
  137.     int xsize, ysize;
  138.  
  139.     static char *compressFilter = "/usr/bsd/compress";
  140.     static char *compFilterArgv0 = "compress";
  141.  
  142.     ConnectionState *sv;
  143.  
  144.  
  145.     sv = _findContext();
  146.  
  147.     data  = frame->data;
  148.     xsize = frame->width;
  149.     ysize = frame->height;
  150.  
  151.     /*** RGB data ***/
  152.     if (frame->packing == VL_PACKING_RGB_8 ||
  153.     frame->packing == VL_PACKING_RGBA_8) {
  154.  
  155.     image = iopen(filename, "w", RLE(1), 3, xsize, ysize, 3);
  156.  
  157.     for (y=0;y<ysize;y++) {
  158.         for(x=0;x<xsize;x++) {
  159.         data++;
  160.         bbuf[x] = (ushort) *(data++);
  161.         gbuf[x] = (ushort) *(data++);
  162.         rbuf[x] = (ushort) *(data++);
  163.         }
  164.         putrow(image, rbuf, ysize - y - 1, 0);
  165.         putrow(image, gbuf, ysize - y - 1, 1);
  166.         putrow(image, bbuf, ysize - y - 1, 2);
  167.     }
  168.  
  169.     iclose(image);
  170.     }
  171.  
  172.     /* other */
  173.     else {
  174.     int image_fd;
  175.     short magic;
  176.     pid_t compress_pid = 0;
  177.     int status;
  178.     struct stat sb;
  179.  
  180.     /*** You would think you could use access(2) to figure
  181.      *** this stuff out, but with EX_OK, it doesn't do the 
  182.      *** checks against our uid and gid to see if the execute
  183.      *** bit is turned on in the right place!
  184.      ***/
  185.     stat(compressFilter, &sb);
  186.     if (sv->saveImagesCompressed &&
  187.         !(sb.st_mode & 0001) &&
  188.         !((sb.st_mode & 0100) && sb.st_uid == geteuid()) &&
  189.         !((sb.st_mode & 0010) && sb.st_gid == getegid()))
  190.         return svCompressMissing;
  191.  
  192.     if (sv->saveImagesCompressed)
  193.         frame->compressed = TRUE;
  194.  
  195.     /* open the file and write the header */
  196.     image_fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC);
  197.     if (image_fd < 0)
  198.         return(svBadFile);
  199.  
  200.     magic = RGB_SV_IMAGE_MAGIC;
  201.     write(image_fd, &magic, 2);
  202.     write(image_fd, frame, sizeof(*frame));
  203.  
  204.     /* Set up compression if called for */
  205.     if (sv->saveImagesCompressed) {
  206.         int fdset[2];            /* [0] read, [1] write */
  207.  
  208.         pipe(fdset);
  209.         if ((compress_pid=fork()) == 0) {
  210.         /* child */
  211.         close(0);
  212.         close(1);
  213.  
  214.         /* setup fds for compress */
  215.         close(fdset[1]);
  216.         dup2(fdset[0], 0);        /* clone fdset[0] into stdin */
  217.         dup2(image_fd, 1);        /* image_fd is the output    */
  218.         execl(compressFilter, compFilterArgv0, (char *)0);
  219.         exit(1);
  220.         }
  221.  
  222.         /* aim image_fd at the pipe to compress */
  223.         close(fdset[0]);
  224.         close(image_fd);
  225.         image_fd = fdset[1];
  226.     }
  227.  
  228.     /* write the data */
  229.     if (write(image_fd, frame->data, (uint) frame->dataSize) < 0) {
  230.         unlink(filename);
  231.         if (sv->saveImagesCompressed)
  232.         return svCompressFailed;
  233.         else
  234.         return svFileWriteFailed;
  235.     }
  236.  
  237.     close(image_fd);
  238.  
  239.     if (compress_pid)
  240.         waitpid(compress_pid, &status, 0);
  241.     }
  242.  
  243.     return 0;
  244. }
  245.  
  246. /**********************************************************************
  247.  * 
  248.  * svLoadImage - 
  249.  *
  250.  * Load an image from a file
  251.  **********************************************************************
  252.  */
  253.  
  254. int 
  255. svLoadImage(char *filename, svImage **userFrame)
  256. {
  257.     int image_fd;
  258.     int count, size;
  259.     short magic;
  260.     char *raster;
  261.     char *ptr;
  262.     svImage *frame;
  263.     IMAGE *image;
  264.     
  265.     static char *uncompressFilter = "/usr/bsd/uncompress";
  266.     static char *uncompFilterArgv0 = "uncompress";
  267.  
  268.     *userFrame = NULL;
  269.  
  270.     /* Open the file, try to read the magic number */
  271.     image_fd = open(filename, O_RDONLY);
  272.     if (image_fd < 0)
  273.     return svBadFile;
  274.  
  275.     read(image_fd, &magic, 2);
  276.  
  277.     /*  If it's RGB image data */
  278.     if (magic == RGB_MAGIC) {
  279.     close(image_fd); 
  280.     image = iopen(filename, "r");
  281.     raster = (char *)longimagedata(filename);
  282.  
  283.     frame = (svImage *) malloc(sizeof(svImage));
  284.     frame->width   = (int) image->xsize;
  285.     frame->height  = (int) image->ysize;
  286.     frame->packing = VL_PACKING_RGB_8;
  287.     frame->data    =  raster;
  288.     frame->dataSize = frame->width * frame->height * 4;
  289.     frame->dataMalloced = TRUE;
  290.     }
  291.     else if (magic == RGB_SV_IMAGE_MAGIC) {
  292.     frame = (svImage *) malloc(sizeof(svImage));
  293.     read(image_fd, frame, sizeof(*frame));
  294.     
  295.     if (frame->compressed) {
  296.         int fdset[2];        /* [0] read, [1] write */
  297.         struct stat sb;
  298.  
  299.         /*** If we used compression, now make sure we will be able
  300.          *** to exec the uncompress program.  See comments above 
  301.          *** about why I'm not using access(2).
  302.          ***/
  303.         stat(uncompressFilter, &sb);
  304.         if (!(sb.st_mode & 0001) &&
  305.         !((sb.st_mode & 0100) && sb.st_uid == geteuid()) &&
  306.         !((sb.st_mode & 0010) && sb.st_gid == getegid()))
  307.         return svCompressMissing;
  308.         
  309.         pipe(fdset);
  310.         if (fork() == 0) {
  311.         /* child */
  312.         close(0);
  313.         close(1);
  314.  
  315.         /* setup fds for uncompress */
  316.         close(fdset[0]);
  317.         dup2(image_fd, 0);     /* image fd is uncompress input */
  318.         dup2(fdset[1], 1);     /* clone fdset[1] to stdout */
  319.         execl(uncompressFilter, uncompFilterArgv0, (char *)0);
  320.         exit(1);
  321.         }
  322.         
  323.         /* aim image_fd at the output from uncompress */
  324.         close(fdset[1]);
  325.         close(image_fd);
  326.         image_fd = fdset[0];
  327.     }
  328.  
  329.     frame->data = malloc((uint)frame->dataSize);
  330.  
  331.     /* Read the frame data - we need the loop 'cause if we're
  332.      * reading from a pipe, we may not get all the data in
  333.      * one shot;
  334.      */
  335.  
  336.     size = frame->dataSize;
  337.     ptr  = frame->data;
  338.     while (size && (count=read(image_fd, ptr, (uint)size)) >= 0) {
  339.         size -= count;
  340.         ptr  += count;
  341.     }
  342.     }
  343.     else
  344.     return svBadFile;
  345.  
  346.     *userFrame = frame;
  347.     
  348.     return 0;
  349. }
  350.  
  351. /**********************************************************************
  352.  * 
  353.  * svViewImage - 
  354.  *
  355.  * Use GL to display an image on screen
  356.  **********************************************************************
  357.  */
  358.  
  359. int
  360. svViewImage(svImage *frame, int x, int y)
  361. {
  362.     int ymax;
  363.  
  364.     if (frame->packing != VL_PACKING_RGB_8 &&
  365.     frame->packing != VL_PACKING_RGBA_8)
  366.     return svBadImageType;
  367.  
  368.     foreground();
  369.     ymax = (int) getgdesc(GD_YPMAX);
  370.     prefsize((long)frame->width, (long)frame->height);
  371.     prefposition((long)x, (long)x+(long)frame->width,
  372.          (long)(ymax-y), (long)(ymax-y-frame->height));
  373.     winopen("");
  374.     RGBmode();
  375.     gconfig();
  376.     pixmode(PM_TTOB, 1);
  377.     lrectwrite(0, 0, (short)(frame->width-1), (short)(frame->height-1),
  378.            (ulong *)frame->data);
  379.  
  380.     return svSuccess;
  381. }
  382.  
  383. /**********************************************************************
  384.  * misc. routines used for reading rgb files;
  385.  **********************************************************************
  386.  */
  387.  
  388. static void
  389. rgbatocpack(unsigned short *r,
  390.         unsigned short *g,
  391.         unsigned short *b,
  392.         unsigned short *a,
  393.         unsigned long *l,
  394.         int n)
  395. {
  396.  
  397.     while(n>=8) {
  398.     l[0] = (ul)r[0] | (ul)(g[0]<<8) | (ul)(b[0]<<16) | (ul)(a[0]<<24);
  399.     l[1] = (ul)r[1] | (ul)(g[1]<<8) | (ul)(b[1]<<16) | (ul)(a[1]<<24);
  400.     l[2] = (ul)r[2] | (ul)(g[2]<<8) | (ul)(b[2]<<16) | (ul)(a[2]<<24);
  401.     l[3] = (ul)r[3] | (ul)(g[3]<<8) | (ul)(b[3]<<16) | (ul)(a[3]<<24);
  402.     l[4] = (ul)r[4] | (ul)(g[4]<<8) | (ul)(b[4]<<16) | (ul)(a[4]<<24);
  403.     l[5] = (ul)r[5] | (ul)(g[5]<<8) | (ul)(b[5]<<16) | (ul)(a[5]<<24);
  404.     l[6] = (ul)r[6] | (ul)(g[6]<<8) | (ul)(b[6]<<16) | (ul)(a[6]<<24);
  405.     l[7] = (ul)r[7] | (ul)(g[7]<<8) | (ul)(b[7]<<16) | (ul)(a[7]<<24);
  406.     l += 8;
  407.     r += 8;
  408.     g += 8;
  409.     b += 8;
  410.     a += 8;
  411.     n -= 8;
  412.     }
  413.     while(n--) 
  414.         *l++ = (ul)*r++|(ul)((*g++)<<8)|(ul)((*b++)<<16)|(ul)((*a++)<<24);
  415. }
  416.  
  417. static void
  418. rgbtocpack(unsigned short *r,
  419.        unsigned short *g,
  420.        unsigned short *b,
  421.        unsigned long *l,
  422.        int n)
  423. {
  424.     while(n>=8) {
  425.     l[0] = (ul)r[0] | (ul)(g[0]<<8) | (ul)(b[0]<<16) | (ul)(0xff<<24);
  426.     l[1] = (ul)r[1] | (ul)(g[1]<<8) | (ul)(b[1]<<16) | (ul)(0xff<<24);
  427.     l[2] = (ul)r[2] | (ul)(g[2]<<8) | (ul)(b[2]<<16) | (ul)(0xff<<24);
  428.     l[3] = (ul)r[3] | (ul)(g[3]<<8) | (ul)(b[3]<<16) | (ul)(0xff<<24);
  429.     l[4] = (ul)r[4] | (ul)(g[4]<<8) | (ul)(b[4]<<16) | (ul)(0xff<<24);
  430.     l[5] = (ul)r[5] | (ul)(g[5]<<8) | (ul)(b[5]<<16) | (ul)(0xff<<24);
  431.     l[6] = (ul)r[6] | (ul)(g[6]<<8) | (ul)(b[6]<<16) | (ul)(0xff<<24);
  432.     l[7] = (ul)r[7] | (ul)(g[7]<<8) | (ul)(b[7]<<16) | (ul)(0xff<<24);
  433.     l += 8;
  434.     r += 8;
  435.     g += 8;
  436.     b += 8;
  437.     n -= 8;
  438.     }
  439.     while(n--) 
  440.         *l++ = (ul)*r++ | (ul)((*g++)<<8) | (ul)((*b++)<<16) | (ul)(0xff<<24);
  441. }
  442.  
  443. /*     cpack -
  444.  *        Convert from and to cpack format.
  445.  *    
  446.  */
  447. static void
  448. bwtocpack(unsigned short *b,
  449.       unsigned long *l,
  450.       int n)
  451. {
  452.     while(n>=8) {
  453.     l[0] = 0xff000000+0x00010101*(ulong)b[0];
  454.     l[1] = 0xff000000+0x00010101*(ulong)b[1];
  455.     l[2] = 0xff000000+0x00010101*(ulong)b[2];
  456.     l[3] = 0xff000000+0x00010101*(ulong)b[3];
  457.     l[4] = 0xff000000+0x00010101*(ulong)b[4];
  458.     l[5] = 0xff000000+0x00010101*(ulong)b[5];
  459.     l[6] = 0xff000000+0x00010101*(ulong)b[6];
  460.     l[7] = 0xff000000+0x00010101*(ulong)b[7];
  461.     l += 8;
  462.     b += 8;
  463.     n -= 8;
  464.     }
  465.     while(n--) 
  466.     *l++ = (ul)0xff000000+(ul)(0x00010101*(*b++));
  467. }
  468.  
  469. static unsigned long *
  470. longimagedata(char *name)
  471. {
  472.     unsigned long *base, *lptr;
  473.     unsigned short *rbuf, *gbuf, *bbuf, *abuf;
  474.     IMAGE *image;
  475.     ushort ysize;
  476.     int y;
  477.  
  478.     image = iopen(name,"r");
  479.     if(!image) {
  480.     fprintf(stderr,"longimagedata: can't open image file %s\n",name);
  481.     exit(1);
  482.     }
  483.  
  484.     base = (ulong *)malloc((uint)image->xsize*(uint)image->ysize*sizeof(long));
  485.     rbuf = (ushort *)malloc((uint)image->xsize*sizeof(short));
  486.     gbuf = (ushort *)malloc((uint)image->xsize*sizeof(short));
  487.     bbuf = (ushort *)malloc((uint)image->xsize*sizeof(short));
  488.     abuf = (ushort *)malloc((uint)image->xsize*sizeof(short));
  489.     if(!base || !rbuf || !gbuf || !bbuf) {
  490.     fprintf(stderr,"longimagedata: can't malloc enough memory\n");
  491.     exit(1);
  492.     }
  493.     lptr = base;
  494.     ysize = image->ysize;
  495.     for(y=0; y<ysize; y++) {
  496.     if(image->zsize>=4) {
  497.         getrow(image,rbuf,ysize-y-1,0);
  498.         getrow(image,gbuf,ysize-y-1,1);
  499.         getrow(image,bbuf,ysize-y-1,2);
  500.         getrow(image,abuf,ysize-y-1,3);
  501.         rgbatocpack(rbuf,gbuf,bbuf,abuf,lptr,(int) image->xsize);
  502.         lptr += (unsigned long) image->xsize;
  503.     } else if(image->zsize==3) {
  504.         getrow(image,rbuf,ysize-y-1,0);
  505.         getrow(image,gbuf,ysize-y-1,1);
  506.         getrow(image,bbuf,ysize-y-1,2);
  507.         rgbtocpack(rbuf,gbuf,bbuf,lptr,(int) image->xsize);
  508.         lptr += (unsigned long) image->xsize;
  509.     } else {
  510.         getrow(image,rbuf,ysize-y-1,0);
  511.         bwtocpack(rbuf,lptr,(int)image->xsize);
  512.         lptr += (unsigned long) image->xsize;
  513.     }
  514.     }
  515.     iclose(image);
  516.     free(rbuf);
  517.     free(gbuf);
  518.     free(bbuf);
  519.     free(abuf);
  520.     return base;
  521. }
  522.