home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 2000 April & May / AMIGA_2000_04.iso / patches / mesa3.1 / util / imagesgi.cpp < prev    next >
C/C++ Source or Header  |  1999-08-18  |  10KB  |  370 lines

  1. /******************************************************************************
  2. ** Filename       : imageSgi.cpp
  3. **                  UNCLASSIFIED
  4. **
  5. ** Description    : Utility to read SGI image format files.  This code was
  6. **                  originally a SGI image loading utility provided with the
  7. **                  Mesa 3D library @ http://www.mesa3d.org by Brain Paul.
  8. **                  This has been extended to read all SGI image formats
  9. **                  (e.g. INT, INTA, RGB, RGBA).
  10. **
  11. ** Revision History:
  12. **   Date       Name   Description
  13. **   06/07/99   BRC    Initial Release
  14. **
  15. ** Note:
  16. **
  17. ** The SGI Image Data (if not RLE)
  18. **
  19. **   If the image is stored verbatim (without RLE), then image data directly
  20. **   follows the 512 byte header.  The data for each scanline of the first
  21. **   channel is written first.  If the image has more than 1 channel, all
  22. **   the data for the first channel is written, followed by the remaining
  23. **   channels.  If the BPC value is 1, then each scanline is written as XSIZE
  24. **   bytes.  If the BPC value is 2, then each scanline is written as XSIZE
  25. **   shorts.  These shorts are stored in the byte order described above.
  26. **
  27. ******************************************************************************/
  28. #define __IMAGESGI_CPP
  29.  
  30. #include "imagesgi.h"
  31.  
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <math.h>
  36. #include <assert.h>
  37.  
  38. struct sImageSgiRaw
  39. {
  40.    struct sImageSgiHeader header;
  41.    unsigned char *chan0;
  42.    unsigned char *chan1;
  43.    unsigned char *chan2;
  44.    unsigned char *chan3;
  45.    unsigned int *rowStart;
  46.    int *rowSize;
  47. };
  48.  
  49. // Static routines
  50. static struct sImageSgiRaw *ImageSgiRawOpen(char const * const fileName);
  51. static void ImageSgiRawClose(struct sImageSgiRaw *raw);
  52. static void ImageSgiRawGetRow(struct sImageSgiRaw *raw, unsigned char *buf,
  53.    int y, int z);
  54. static void ImageSgiRawGetData(struct sImageSgiRaw *raw, struct sImageSgi 
  55. *final);
  56. static void *SwitchEndian16(void *value);
  57. static void *SwitchEndian32(void *value);
  58.  
  59. // Static variables
  60. FILE *mFp = NULL;
  61. unsigned char *mChanTmp = NULL;
  62.  
  63.  
  64. /*****************************************************************************/
  65. struct sImageSgi *ImageSgiOpen(char const * const fileName)
  66. {
  67.    struct sImageSgiRaw *raw = NULL;
  68.    struct sImageSgi *final = NULL;
  69.  
  70.    raw = ImageSgiRawOpen(fileName);
  71.    final = new struct sImageSgi;
  72.  
  73.    assert(final);
  74.    if(final)
  75.    {
  76.       final->header = raw->header;
  77.       final->data = NULL;
  78.       ImageSgiRawGetData(raw, final);
  79.       ImageSgiRawClose(raw);
  80.    }
  81.  
  82.    return final;
  83. } // ImageSgiRawOpen
  84.  
  85.  
  86. /*****************************************************************************/
  87. void ImageSgiClose(struct sImageSgi *image)
  88. {
  89.  
  90.    if(image)
  91.    {
  92.       if(image->data)
  93.          delete[] image->data;
  94.       image->data = NULL;
  95.       delete image;
  96.    }
  97.    image = NULL;
  98.  
  99.    return;
  100. } // ImageSgiClose
  101.  
  102.  
  103. /*****************************************************************************/
  104. static struct sImageSgiRaw *ImageSgiRawOpen(char const * const fileName)
  105. {
  106.    struct sImageSgiRaw *raw = NULL;
  107.    int x;
  108.    int i;
  109.    bool swapFlag = false;
  110.    union
  111.    {
  112.       int testWord;
  113.       char testByte[4];
  114.    } endianTest;
  115.    endianTest.testWord = 1;
  116.  
  117.    // Determine endianess of platform.
  118.    if(endianTest.testByte[0] == 1)
  119.       swapFlag = true;
  120.    else
  121.       swapFlag = false;
  122.  
  123.    raw = new struct sImageSgiRaw;
  124.  
  125.    assert(raw);
  126.    if(raw)
  127.    {
  128.       raw->chan0 = NULL;
  129.       raw->chan1 = NULL;
  130.       raw->chan2 = NULL;
  131.       raw->chan3 = NULL;
  132.       raw->rowStart = NULL;
  133.       raw->rowSize = NULL;
  134.       mFp = fopen(fileName, "rb");
  135.       assert(mFp);
  136.  
  137.       fread(&raw->header, sizeof(struct sImageSgiHeader), 1, mFp);
  138.       if(swapFlag == true)
  139.       {
  140.          SwitchEndian16(&raw->header.magic);
  141.          SwitchEndian16(&raw->header.type);
  142.          SwitchEndian16(&raw->header.dim);
  143.          SwitchEndian16(&raw->header.xsize);
  144.          SwitchEndian16(&raw->header.ysize);
  145.          SwitchEndian16(&raw->header.zsize);
  146.       }
  147.  
  148.       mChanTmp = new unsigned char[raw->header.xsize * raw->header.ysize];
  149.       assert(mChanTmp);
  150.       switch(raw->header.zsize)
  151.       {
  152.       case 4:
  153.          raw->chan3 = new unsigned char[raw->header.xsize * 
  154. raw->header.ysize];
  155.          assert(raw->chan3);
  156.       case 3:
  157.          raw->chan2 = new unsigned char[raw->header.xsize * 
  158. raw->header.ysize];
  159.          assert(raw->chan2);
  160.       case 2:
  161.          raw->chan1 = new unsigned char[raw->header.xsize * 
  162. raw->header.ysize];
  163.          assert(raw->chan1);
  164.       case 1:
  165.          raw->chan0 = new unsigned char[raw->header.xsize * 
  166. raw->header.ysize];
  167.          assert(raw->chan0);
  168.       }
  169.  
  170.       if(raw->header.type == IMAGE_SGI_TYPE_RLE)
  171.       {
  172.          x = raw->header.ysize * raw->header.zsize * sizeof(unsigned int);
  173.          raw->rowStart = new unsigned int[x];
  174.          raw->rowSize = new int[x];
  175.  
  176.          fseek(mFp, sizeof(struct sImageSgiHeader), SEEK_SET);
  177.          fread(raw->rowStart, 1, x, mFp);
  178.          fread(raw->rowSize, 1, x, mFp);
  179.  
  180.          if(swapFlag == true)
  181.          {
  182.             for(i=0; i<x/sizeof(unsigned int); i++)
  183.                SwitchEndian32(&raw->rowStart[i]);
  184.             for(i=0; i<x/sizeof(int); i++)
  185.                SwitchEndian32(&raw->rowSize[i]);
  186.          }
  187.  
  188.       }
  189.  
  190.    }
  191.  
  192.    return raw;
  193. } // ImageSgiRawOpen
  194.  
  195.  
  196. /*****************************************************************************/
  197. static void ImageSgiRawClose(struct sImageSgiRaw *raw)
  198. {
  199.  
  200.    fclose(mFp);
  201.    mFp = NULL;
  202.  
  203.    if(mChanTmp)
  204.       delete[] mChanTmp;
  205.    mChanTmp = NULL;
  206.  
  207.    if(raw->chan0)
  208.       delete[] raw->chan0;
  209.    raw->chan0 = NULL;
  210.  
  211.    if(raw->chan1)
  212.       delete[] raw->chan1;
  213.    raw->chan1 = NULL;
  214.  
  215.    if(raw->chan2)
  216.       delete[] raw->chan2;
  217.    raw->chan2 = NULL;
  218.  
  219.    if(raw->chan3)
  220.       delete[] raw->chan3;
  221.    raw->chan3 = NULL;
  222.  
  223.    if(raw)
  224.       delete raw;
  225.    raw = NULL;
  226.  
  227.    return;
  228. } // ImageSgiRawClose
  229.  
  230.  
  231. /*****************************************************************************/
  232. static void ImageSgiRawGetRow(struct sImageSgiRaw *raw, unsigned char *buf,
  233.    int y, int z)
  234. {
  235.    unsigned char *iPtr = NULL;
  236.    unsigned char *oPtr = NULL;
  237.    unsigned char pixel;
  238.    int count;
  239.  
  240.    if((raw->header.type & 0xFF00) == 0x0100)
  241.    {
  242.       fseek(mFp, raw->rowStart[y+z*raw->header.ysize], SEEK_SET);
  243.       fread(mChanTmp, 1, (unsigned int)raw->rowSize[y+z*raw->header.ysize], 
  244. mFp);
  245.       iPtr = mChanTmp;
  246.       oPtr = buf;
  247.       while(1)
  248.       {
  249.          pixel = *iPtr++;
  250.          count = (int)(pixel & 0x7F);
  251.          if(!count)
  252.          {
  253.             return;
  254.          }
  255.          if (pixel & 0x80)
  256.          {
  257.             while (count--)
  258.             {
  259.                *oPtr++ = *iPtr++;
  260.             }
  261.          }
  262.          else
  263.          {
  264.             pixel = *iPtr++;
  265.             while (count--)
  266.             {
  267.                *oPtr++ = pixel;
  268.             }
  269.          }
  270.       }
  271.    }
  272.    else
  273.    {
  274.       fseek(mFp,
  275.          sizeof(struct sImageSgiHeader)+(y*raw->header.xsize) +
  276.             (z*raw->header.xsize*raw->header.ysize),
  277.          SEEK_SET);
  278.       fread(buf, 1, raw->header.xsize, mFp);
  279.    }
  280.  
  281.    return;
  282. } // ImageSgiRawGetRow
  283.  
  284.  
  285. /*****************************************************************************/
  286. static void ImageSgiRawGetData(struct sImageSgiRaw *raw, struct sImageSgi 
  287. *final)
  288. {
  289.    unsigned char *ptr = NULL;
  290.    int i, j;
  291.  
  292.    final->data =
  293.       new unsigned 
  294. char[raw->header.xsize*raw->header.ysize*raw->header.zsize];
  295.    assert(final->data);
  296.  
  297.    ptr = final->data;
  298.    for(i=0; i<raw->header.ysize; i++)
  299.    {
  300.       switch(raw->header.zsize)
  301.       {
  302.       case 1:
  303.          ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  304.          for(j=0; j<raw->header.xsize; j++)
  305.             *(ptr++) = raw->chan0[j];
  306.          break;
  307.       case 2:
  308.          ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  309.          ImageSgiRawGetRow(raw, raw->chan1, i, 1);
  310.          for(j=0; j<raw->header.xsize; j++)
  311.          {
  312.             *(ptr++) = raw->chan0[j];
  313.             *(ptr++) = raw->chan1[j];
  314.          }
  315.          break;
  316.       case 3:
  317.          ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  318.          ImageSgiRawGetRow(raw, raw->chan1, i, 1);
  319.          ImageSgiRawGetRow(raw, raw->chan2, i, 2);
  320.          for(j=0; j<raw->header.xsize; j++)
  321.          {
  322.             *(ptr++) = raw->chan0[j];
  323.             *(ptr++) = raw->chan1[j];
  324.             *(ptr++) = raw->chan2[j];
  325.          }
  326.          break;
  327.       case 4:
  328.          ImageSgiRawGetRow(raw, raw->chan0, i, 0);
  329.          ImageSgiRawGetRow(raw, raw->chan1, i, 1);
  330.          ImageSgiRawGetRow(raw, raw->chan2, i, 2);
  331.          ImageSgiRawGetRow(raw, raw->chan3, i, 3);
  332.          for(j=0; j<raw->header.xsize; j++)
  333.          {
  334.             *(ptr++) = raw->chan0[j];
  335.             *(ptr++) = raw->chan1[j];
  336.             *(ptr++) = raw->chan2[j];
  337.             *(ptr++) = raw->chan3[j];
  338.          }
  339.          break;
  340.       }
  341.    }
  342.  
  343.    return;
  344. } // ImageSgiRawGetData
  345.  
  346.  
  347. /*****************************************************************************/
  348. static void *SwitchEndian16(void *value)
  349. {
  350.    short value16 = *(short *) value;
  351.    value16 = ((value16 & 0xff00) >> 8L) +
  352.              ((value16 & 0x00ff) << 8L);
  353.    *(short *)value = value16;
  354.    return value;
  355. } // SwitchEndian16
  356.  
  357.  
  358. /*****************************************************************************/
  359. static void *SwitchEndian32(void *value)
  360. {
  361.    int value32 = *(int *) value;
  362.    value32 = ((value32 & 0xff000000) >> 24L) +
  363.              ((value32 & 0x00ff0000) >> 8)   +
  364.              ((value32 & 0x0000ff00) << 8)   +
  365.              ((value32 & 0x000000ff) << 24L);
  366.    *(int *)value = value32;
  367.    return value;
  368. } // SwitchEndian32
  369.  
  370.