home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / pal / tga.c < prev   
C/C++ Source or Header  |  1998-06-08  |  9KB  |  325 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <conio.h>
  16. #include <math.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <fcntl.h>
  21. #include <io.h>
  22. #include <dos.h>
  23. #include <malloc.h>
  24. #include <ctype.h>
  25.  
  26. typedef unsigned char   BYTE;
  27. typedef unsigned short  WORD;
  28. typedef unsigned int    DWORD;
  29.  
  30. typedef struct
  31. {
  32.      BYTE  Field1;
  33.      BYTE  Field2;
  34.      BYTE  DataType ;
  35.      BYTE  Field41H ;
  36.      BYTE  Field41L ;
  37.      BYTE  Field42H ;
  38.      BYTE  Field42L ;
  39.      BYTE  Field43  ;
  40.      WORD  XOrigin  ;
  41.      WORD  YOrigin  ;
  42.      WORD  Width    ;
  43.      WORD  Height   ;
  44.      BYTE  BitsPerPixel;
  45.      BYTE  Field56  ;
  46. } TGA_FILE_HEADER;
  47.  
  48. typedef struct  {
  49.     WORD        Width;
  50.     WORD        Height;
  51.     WORD        Data[1];
  52. } BITMAP15;
  53.  
  54. BITMAP15 * ReadInTGA(char * filename )
  55. {
  56.     BITMAP15 * NewBitmap;
  57.     short row_b,col_b,row_e,col_e;
  58.     char *buffer;
  59.     TGA_FILE_HEADER imghead;
  60.     int infile;
  61.     int numread;
  62.     short len ;
  63.     short row,dcol,col_now,drow;
  64.     char quitflag ;
  65.     WORD bufindex, value ;
  66.     BYTE  count;
  67.     short tempcnt;
  68.     short BufSize, RowsPerRead, BytesPerRow;
  69.     short i;
  70.     WORD tmpbuf[320];
  71.  
  72.     // Try to open file
  73.  
  74.     infile = open(filename,(O_BINARY|O_RDONLY) ) ;
  75.     if (infile==-1) {
  76.         printf( "TGAto15BPP: '%s' not found.\n", filename );
  77.         return NULL;
  78.     }
  79.  
  80.     // Read the image header
  81.     numread = read(infile,(char*)&imghead, sizeof(TGA_FILE_HEADER) ) ;
  82.     if ( numread != sizeof(TGA_FILE_HEADER) )     {
  83.         printf( "TGAto15BPP: Error reading '%s' header.\n", filename );
  84.         close(infile);
  85.         return NULL;
  86.     }
  87.  
  88.     //  get the data in header
  89.     dcol  = imghead.Width;
  90.     drow  = imghead.Height;
  91.  
  92.     // Assign column,row begin , displacement to input Origion
  93.     col_b = imghead.XOrigin ;
  94.     row_b = imghead.YOrigin ;
  95.     col_b = 0 ;
  96.     row_b = 0 ;
  97.  
  98.     // check if orgion overflow
  99.     if ( (row_b>320) || (col_b>480) )   {
  100.         printf( "TGAto15BPP: Origin overflow reading '%s'.", filename );
  101.         close(infile);
  102.         return NULL;
  103.     }
  104.  
  105.     // Bound the image in maxrow, maxcal
  106.     col_e = dcol + col_b - 1 ;
  107.     row_e = drow + row_b - 1 ;
  108.     if (col_e>320)
  109.         col_e = 320 ;
  110.     if (row_e>480)
  111.         row_e = 480 ;
  112.  
  113.     // check if 16 bits per pixel, now support VIGA16 file only
  114.     if (imghead.BitsPerPixel != 16 )    {
  115.         printf( "TGAto15BPP: '%s' is not a valid 16bpp TGA file.\n", filename );
  116.         close(infile);
  117.         return NULL;
  118.     }
  119.  
  120.     NewBitmap = (BITMAP15 *)malloc( sizeof(BITMAP15)+((col_e-col_b+1)*(row_e-row_b+1)*3) );
  121.     if (NewBitmap == NULL ) {
  122.         printf( "TGAto15bpp: Error allocating bitmap memory for '%s'.\n", filename );
  123.         return NULL;
  124.     }
  125.     NewBitmap->Height = row_e - row_b + 1;
  126.     NewBitmap->Width =  col_e - col_b + 1;
  127.  
  128.     // allocate a buffer as large as possible
  129.     BufSize =  1024;
  130.     while ( ((buffer=(char *)malloc((size_t)BufSize))==NULL) && (BufSize>=1024) )   {
  131.         BufSize -= 1024 ;
  132.     }
  133.  
  134.     // check if buffer enough, if not return MEMORY FULL
  135.     if (BufSize<1024)   {
  136.         printf( "TGAto15BPP: Error allocating buffer for '%s'.\n", filename );
  137.         close(infile);
  138.         free( buffer );
  139.         free( NewBitmap);
  140.         return NULL;
  141.     }
  142.  
  143.     BytesPerRow = dcol * 2 ;
  144.     RowsPerRead = BufSize / BytesPerRow  ;
  145.  
  146.     // Load image file routines...
  147.  
  148.     if (imghead.DataType == 2)   {
  149.         // This image file is not compressed
  150.  
  151.         row = row_b ;
  152.         while (row <= row_e)    {
  153.             if ( (row+RowsPerRead) > row_e)
  154.                 RowsPerRead = row_e - row + 1;
  155.             read(infile,buffer,BytesPerRow*RowsPerRead);
  156.             bufindex = 0 ;
  157.             for (value=0; value<RowsPerRead; value++)   {
  158.                 for (i=col_b; i<=col_e; i++ )
  159.                     memcpy( &(NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ]), &(buffer[bufindex+2*(i-col_b)]), 2 );
  160.                     //NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ] = buffer[bufindex+i-col_b];
  161.                 row++;
  162.                 bufindex += BytesPerRow ;
  163.             } // for
  164.         } // while
  165.         // free the allocated buffer, close opened file
  166.         free(buffer) ;
  167.         close(infile);
  168.         return NewBitmap;
  169.     }
  170.  
  171.     if (imghead.DataType != 10)   {
  172.         // Not a valid TGA file. Free the allocated buffer, close opened file
  173.         printf( "TGAto15BPP: '%s' compression type is invalid.\n", filename );
  174.         free(buffer) ;
  175.         close(infile);
  176.         free( NewBitmap);
  177.         return  NULL;
  178.     }
  179.  
  180.     // init col_now, quitflag to 0,init row to the start row
  181.     col_now = 0 ;
  182.     row = row_b ;
  183.     quitflag = 0 ;
  184.  
  185.     // read a block of data to buffer
  186.     numread = read(infile,buffer,BufSize);
  187.  
  188.     while ( (numread>0) && (quitflag==0) )   {
  189.  
  190.         // init bufindex, while loop to decode data
  191.         bufindex = 0 ;
  192.  
  193.         while ( (bufindex<numread) && (quitflag==0) )  {
  194.             // get the first data in buffer, inc bufindex
  195.  
  196.             count =  *(buffer+bufindex) ;
  197.             bufindex++;
  198.  
  199.             // check if count a data or a counter
  200.  
  201.             if ( count >= 128 ) {
  202.                 // if end of buffer, read next block, and continue to decode them
  203.                 if (bufindex>=numread)  {
  204.                     numread = read(infile,buffer,BufSize) ;
  205.                     if (numread>0)  {
  206.                         bufindex = 0 ;
  207.                         memcpy(&value,(buffer+bufindex),2);
  208.                         bufindex += 2 ;
  209.                     }
  210.                     else
  211.                         quitflag = 1 ;
  212.                 }
  213.                 else
  214.                     if ( (bufindex+1) >= numread )  {
  215.                         value = *(buffer+bufindex) ;
  216.                         numread = read(infile,buffer,BufSize) ;
  217.                         if (numread>0)  {
  218.                             bufindex = 0 ;
  219.                             value += *(buffer+bufindex) << 8 ;
  220.                             bufindex++;
  221.                         }
  222.                         else
  223.                             quitflag = 1 ;
  224.                     }
  225.                     else    {
  226.                         memcpy(&value,(buffer+bufindex),2);
  227.                         bufindex += 2 ;
  228.                     }
  229.  
  230.                 // dec count by 127, store data to
  231.                 // tmpbuf, adjust col_now
  232.  
  233.                 count -= 127 ;    // 127
  234.                 while (count>0)   {
  235.                     tmpbuf[col_now] = value ;
  236.                     col_now++;
  237.                     count--;
  238.                 } // while
  239.             } // if count
  240.             else    {
  241.                 // not counter, inc count, cal tempcnt
  242.                 count++;
  243.                 tempcnt = 2*count ;
  244.  
  245.                 // check if end of buffer, if yes read next
  246.                 // block to buffer, continue to decode
  247.                 if ( (bufindex+tempcnt) >= numread )    {
  248.                     while ( (bufindex+2)<=numread )   {
  249.                         memcpy(&tmpbuf[col_now],(buffer+bufindex), 2);
  250.                         col_now++;
  251.                         tempcnt -= 2 ;
  252.                         bufindex += 2 ;
  253.                     }
  254.                     if ( bufindex<numread ) {
  255.                         value = *(buffer+bufindex) ;
  256.                         numread = read(infile,buffer,BufSize) ;
  257.                         if (numread>0)  {
  258.                             bufindex = 0 ;
  259.                             value += *(buffer+bufindex) << 8 ;
  260.                             tmpbuf[col_now] = value ;
  261.                             col_now++;
  262.                             bufindex++;
  263.                             tempcnt -= 2 ;
  264.                         }
  265.                         else
  266.                             quitflag = 1 ;
  267.                     }
  268.                     else
  269.                     {
  270.                         numread = read(infile,buffer,BufSize) ;
  271.                         if (numread>0)
  272.                             bufindex = 0 ;
  273.                         else
  274.                             quitflag = 1 ;
  275.                     }
  276.                     if (tempcnt>0)
  277.                     {
  278.                         memcpy(&tmpbuf[col_now],(buffer+bufindex), tempcnt) ;
  279.                         col_now += ( tempcnt / 2) ;
  280.                         bufindex += tempcnt ;
  281.                     } // if tempcnt
  282.                 }  // if buffindex
  283.                 else
  284.                 {
  285.                     memcpy(&tmpbuf[col_now],(buffer+bufindex),tempcnt);
  286.                     bufindex += tempcnt ;
  287.                     col_now += count;
  288.                 } // else buffindex
  289.             } // else count
  290.  
  291.             // check if tmpbuf enough to be a row, if yes
  292.             // output the row to board, inc row
  293.             if ( col_now>=dcol )
  294.             {
  295.                 for (i=col_b; i<=col_e; i++ )
  296.                     NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ] = tmpbuf[i-col_b];
  297.                 row++;
  298.                 if (row>row_e)
  299.                     quitflag = 1 ;
  300.                 len = col_now - dcol ;
  301.                 if (len>0)
  302.                     memcpy(&tmpbuf[0],&tmpbuf[dcol], (2*len) ) ;
  303.                 col_now = len;
  304.             } // if col_now >dcol
  305.         } // while bufindex
  306.  
  307.         // read another block to be decoded
  308.         numread = read(infile,buffer,BufSize) ;
  309.     } // while numread
  310.  
  311.     // if there were some data in tmpbuf, output it
  312.     if (col_now>0)  {
  313.         for (i=col_b; i<=(col_e+col_now); i++ )
  314.             NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ] = tmpbuf[i-col_b];
  315.     }
  316.  
  317.     // free the allocated buffer, close opened file
  318.     free(buffer) ;
  319.     close(infile);
  320.     return NewBitmap;
  321.  
  322. }
  323.  
  324.  
  325.