home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / pascal / rehack / graphics / bitmap.cpp next >
Encoding:
C/C++ Source or Header  |  1993-07-26  |  9.9 KB  |  389 lines

  1. //---------------------------------------------------------------------------
  2. //
  3. //      File:           BITMAP.CPP
  4. //      Path:           ...\REHACK\graphics
  5. //      Version:                1.1
  6. //      Author:         Dave Boynton
  7. //      CIS Id:            71043,317
  8. //      Created On:     6/26/93
  9. //      Modified On:    7/25/93
  10. //      Description:    Bitmap class methods, requires pcx256 & display
  11. //                        classes.
  12. //      Tabs:           4
  13. //
  14. //---------------------------------------------------------------------------
  15. // copyright (c) 1993 by the GAMERS Forum, Rehack project team.
  16. // All rights reserved.
  17. #include <alloc.h>
  18. #include <dos.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <mem.h>
  23. #include "..\general\types.hpp"
  24. #include "..\general\misc.hpp"
  25. #include "..\graphics\pcx.hpp"
  26. #include "..\graphics\bitmap.hpp"
  27. #include "..\graphics\display.hpp"
  28.  
  29. // -------------------------- Bitmap --------------------------------
  30. Bitmap::Bitmap(word width, word height, bool Direct)
  31. {
  32.     memset(this, 0, sizeof(Bitmap));
  33.     validFlag=true;
  34.     if ( Direct )
  35.     {
  36.         directFlag=true;
  37.         BitmapSetup(width,height);
  38.         // bits must be set externally
  39.     } else {
  40.         directFlag=false;
  41.         BitmapSetup(width, height);
  42.         bits=new byte[(word)(width * height)];
  43.         if ( bits )
  44.             memset(bits,0,width*height);
  45.         else
  46.             validFlag=false;
  47.     }
  48. }
  49.  
  50. Bitmap::Bitmap(const OwnerRect &theBounds)
  51. {
  52.     memset(this, 0, sizeof(Bitmap));
  53.     word sizeX, sizeY;
  54.     sizeX=(theBounds.bottomRight.x - theBounds.topLeft.x);
  55.     sizeY=(theBounds.bottomRight.y - theBounds.topLeft.y);
  56.  
  57.     directFlag=false;
  58.     BitmapSetup(sizeX, sizeY);
  59.     bits=new byte[sizeX * sizeY];
  60.     if ( bits )
  61.     {
  62.         ownerBounds=theBounds;
  63.     } else
  64.         validFlag=false;
  65. }
  66.  
  67. Bitmap::Bitmap(char *filename, BitmapFileType fileType)
  68. {
  69.     memset(this, 0, sizeof(Bitmap));
  70.     validFlag=false;
  71.     if ( ( fileType == detect ) &&
  72.          ( (fileType=detectFileType(filename)) == 0 ) )
  73.         return;
  74.  
  75.     FILE *fp;
  76.     if ( (fp=fopen(filename,"rb")) != NULL )
  77.     {
  78.         BitmapLoad(fp, fileType);
  79.         fclose(fp);
  80.     } // end fopen's else
  81. }
  82.  
  83. Bitmap::Bitmap(FILE *fp, BitmapFileType fileType)
  84. { // presumably within a resource file
  85.     memset(this, 0, sizeof(Bitmap));
  86.     validFlag=false;
  87.     BitmapLoad(fp, fileType);    // takes care of everything
  88. }
  89.  
  90. BitmapFileType Bitmap::detectFileType(char *filename)
  91. {
  92.     switch ( *(filename+strlen(filename)-1) )
  93.     {
  94.         case 'x':
  95.         case 'X':
  96.                     return pcx;
  97.         case 'g':
  98.         case 'G':
  99.                     return img;
  100.         case 'a':
  101.         case 'A':
  102.                     return vga;
  103.         default:
  104.                     return detect;
  105.     }
  106. }
  107.  
  108. // if bitmap.validFlag=false, this does a BitmapSetup with the file's
  109. // attributes and allocates memory for the bitmap
  110. void Bitmap::BitmapLoad(FILE *fp, BitmapFileType fileType)
  111. {
  112.     switch (fileType)
  113.     {
  114.         case vga:    // BGI graphics file, .VGA, as used by MVP Paint
  115.                     // struct vgaFile {
  116.                     //        word widthMinusOne, heightMinusOne;
  117.                     //        byte pixels[(widthMinusOne+1) * (heightMinusOne+1)];
  118.                     //        byte padding[];        // this is useless, but the
  119.                     //                            // filesize must be correct
  120.                     //                            // or MVP won't read it
  121.                     //        byte palette[768];  // (optional)
  122.                     // };
  123.  
  124.         case img:    // ACK-3d file, .IMG
  125.                     // struct imgFile {
  126.                     //        word width, height; // img_ed & ack assume 64x64
  127.                     //        byte pixels[width*height];
  128.                     // };
  129.  
  130.             word fsizeX, fsizeY;
  131.             if ( ( fread(&fsizeX,sizeof(fsizeX),1,fp) == 1 ) &&
  132.                      ( fread(&fsizeY,sizeof(fsizeY),1,fp) == 1 ) )
  133.             {
  134.                 word sizeX, sizeY;
  135.                 if ( validFlag == false )
  136.                 {
  137.                     sizeX=fsizeX; sizeY=fsizeY;
  138.                     if ( fileType == img )
  139.                     {
  140.                         directFlag=false;
  141.                         BitmapSetup(sizeX, sizeY);
  142.                         bits=new byte[sizeX * sizeY];
  143.                     } else {// == vga
  144.                         BitmapSetup(sizeX+1, sizeY+1);
  145.                         bits=new byte[(sizeX+1) * (sizeY+1)];
  146.                     }
  147.                     if ( bits == NULL )
  148.                         validFlag=false;
  149.                     if ( validFlag == false )
  150.                         return;
  151.                 } else {
  152.                     // the bitmap is already established, and may be
  153.                     // a different size than the file
  154.                     sizeX=localBounds.bottomRight.x;
  155.                     sizeY=localBounds.bottomRight.y;
  156.                     if ( sizeY > fsizeY )
  157.                         sizeY=fsizeY;
  158.                 }
  159.                 word row;
  160.                 if ( fsizeX > sizeX )
  161.                 {
  162.                     word colSkip=fsizeX - sizeX;
  163.                     for (row=0; row<sizeY; row++)
  164.                     {
  165.                         if ( (fread(bits+(row*sizeX), sizeX, 1, fp) != 1) ||
  166.                              (fseek(fp, colSkip, SEEK_CUR) != 0 ) )
  167.                         {
  168.                             invalidate();
  169.                             return;
  170.                         }
  171.                     }
  172.                 } else {
  173.                     for (row=0; row<sizeY; row++)
  174.                     {
  175.                         if ( fread(bits+(row*sizeX), fsizeX, 1, fp) != 1 )
  176.                         {
  177.                             invalidate();
  178.                             return;
  179.                         }
  180.                     }
  181.                 }
  182.             } // end fread sizes
  183.             break;    // end cases: img vga
  184.  
  185.         case pcx:    // ZSoft PC-Paintbrush file, widely supported
  186.                     // for format details, download pcxref.txt
  187.              PcxFile256 pcx(fp); //opens and reads header
  188.              if ( pcx.validFlag == false )
  189.                 validFlag=false;
  190.              else {
  191.                 if ( validFlag == false )
  192.                 {
  193.                     directFlag=false;
  194.                     BitmapSetup(pcx.hPixels, pcx.vPixels);
  195.                     if ( validFlag )
  196.                     {
  197.                         bits=new byte[pcx.hPixels * pcx.vPixels];
  198.                         if ( bits )
  199.                             memset(bits,0,pcx.hPixels*pcx.vPixels);
  200.                         else {
  201.                             validFlag=false;
  202.                             return;
  203.                         }
  204.                     }
  205.                 }
  206.                 if ( validFlag )
  207.                 {
  208.                     word row;
  209.                     word sizeX, sizeY, cSizeX;
  210.  
  211.                     sizeX=localBounds.bottomRight.x;
  212.                     sizeY=localBounds.bottomRight.y;
  213.                     if ( pcx.vPixels < sizeY )
  214.                         sizeY=pcx.vPixels;
  215.                     if ( pcx.hPixels > sizeX )
  216.                         cSizeX=sizeX;
  217.                     else
  218.                         cSizeX=pcx.hPixels;
  219.  
  220.                     assert( cSizeX <= sizeX );
  221.                     assert( (sizeY<201) && (sizeX<321) );
  222.  
  223.                     for(row=0; row<sizeY; row++)
  224.                     {
  225.                         pcx.readLine( bits + (row * sizeX), 0, cSizeX-1);
  226.                     } // end for()
  227.                 } // end if ( type != 0 )
  228.              }
  229.              break;    // end case: pcx
  230.  
  231.         default:
  232.              validFlag=false;    // just to make sure nothing gets by
  233.              break;
  234.  
  235.     } // end switch (fileType)
  236. }
  237.  
  238. bool Bitmap::BitmapSetup(word width, word height)
  239. {
  240.     if ( ( width > 320 ) || ( height > 200 ) ||
  241.          ( ((long)width * (long)height) > 0x0000ffffL ) )
  242.         validFlag=false;
  243.     else {
  244.         if ( (validFlag) && (directFlag == false) && (bits != NULL) )
  245.             invalidate();
  246.         validFlag=true; dropoutColor=-1;
  247.         localBounds.topLeft.x=0; localBounds.topLeft.y=0;
  248.         localBounds.bottomRight.x=width;
  249.         localBounds.bottomRight.y=height;
  250.         viewPort=localBounds;
  251.         ownerBounds=localBounds;
  252.     }
  253.     return validFlag;
  254. }
  255.  
  256. void Bitmap::invalidate(void)
  257. {
  258.     if ( (validFlag) && (directFlag == false) && (bits != NULL) )
  259.         delete [] bits;
  260.     validFlag=false; bits=NULL;
  261. }
  262.  
  263. long Bitmap::getBitSize(Rect &bounds)
  264. {
  265.     return  (bounds.bottomRight.x - bounds.topLeft.x) *
  266.             (bounds.bottomRight.y - bounds.topLeft.y);
  267. }
  268.  
  269. // copy this' viewPort onto dest's viewPort, offset by Point &at (which
  270. // is relative to the bitmap's viewPort.
  271. void Bitmap::paint(Bitmap *dest, const Point &at)
  272. {
  273.     Rect srcSize, destSize, srcRect, destRect; // destRect is local to dest
  274.  
  275.     destRect= (dest->viewPort + at) & dest->viewPort;
  276.     destSize=destRect - destRect.topLeft; // shift to topLeft={ 0,0 },
  277.                                           // bottomRight becomes size
  278.  
  279.     srcSize= (viewPort - viewPort.topLeft) & destSize;
  280.     srcRect= (srcSize + viewPort.topLeft);
  281.     destRect &= (srcSize + destRect.topLeft);
  282.     // srcRect and destRect are now the same size, but local to their own
  283.     // bitmap.
  284.  
  285.     if ( srcRect.isEmpty() || destRect.isEmpty() )
  286.         return;
  287.  
  288.     byte * srcPtr;
  289.     byte * destPtr;
  290.     word srcWidth, destWidth, copyWidth;
  291.  
  292.     srcWidth=localBounds.bottomRight.x - localBounds.topLeft.x;
  293.     destWidth=dest->localBounds.bottomRight.x - dest->localBounds.topLeft.x;
  294.     copyWidth=srcRect.bottomRight.x - srcRect.topLeft.x;
  295.  
  296.     srcPtr=(srcRect.topLeft.y * srcWidth) + srcRect.topLeft.x + bits;
  297.     destPtr=(destRect.topLeft.y * destWidth) + destRect.topLeft.x + dest->bits;
  298.  
  299.     if ( directFlag )
  300.     {
  301.         // VESA modes and Mode X will have to do something different.
  302.         // If waiting for retraces or page flipping is necessary, then
  303.         // it should be done here as well.
  304.     }
  305.     if ( dropoutColor == -1 )
  306.     {
  307.         word i;
  308.         for (i=srcRect.topLeft.y; i<srcRect.bottomRight.y; i++)
  309.         {
  310.             memcpy(destPtr, srcPtr, copyWidth);
  311.             destPtr+=destWidth;
  312.             srcPtr+=srcWidth;
  313.         }
  314.     } else {
  315.         word i;
  316.         register word j;
  317.         register byte c;
  318.         // this needs heavy optimization!
  319.         // an assembly routine using SCASB or SCASW I'd guess.
  320.         for (i=srcRect.topLeft.y; i<srcRect.bottomRight.y; i++)
  321.             for (j=0; j<copyWidth; j++)
  322.             {
  323.                 c=*(srcPtr+j);
  324.                 if ( c != dropoutColor )
  325.                     *(destPtr+j)=c;
  326.             }
  327.     } // end if (dropoutColor == -1) {} else
  328. }
  329.  
  330. // -------------------------- BitmapArray --------------------------------
  331. BitmapArray::BitmapArray(char *filename, Point TileSize,
  332.                          word XTiles, word YTiles, BitmapFileType FileType)
  333.     : Bitmap(TileSize.x * XTiles, TileSize.y * YTiles)
  334. {
  335.     if ( ( FileType == detect ) &&
  336.          ( (FileType=detectFileType(filename)) == 0 ) )
  337.     {
  338.         validFlag=false;
  339.         return;
  340.     }
  341.  
  342.     FILE *fp;
  343.     if ( (fp=fopen(filename,"rb")) == NULL )
  344.     {
  345.         invalidate();
  346.         return;
  347.     }
  348.     BitmapLoad(fp,FileType);
  349.     fclose(fp);
  350.  
  351.     tileSize=TileSize;
  352.     xTiles=XTiles; yTiles=YTiles;
  353.     setIndex(0,0);
  354. }
  355.  
  356. BitmapArray::BitmapArray(FILE *fp, Point TileSize, word XTiles, word YTiles,
  357.                          BitmapFileType FileType)
  358.     : Bitmap(TileSize.x * XTiles, TileSize.y * YTiles)
  359. {
  360.     BitmapLoad(fp, FileType);
  361.     tileSize=TileSize;
  362.     xTiles=XTiles; yTiles=YTiles;
  363.     setIndex( 0, 0 ); // sets viewPort to tile 0,0
  364. }
  365.  
  366. void BitmapArray::setIndex(word xIndex, word yIndex)
  367. {
  368.     if ( yIndex > yTiles )
  369.         yIndex=yTiles;
  370.     if ( yIndex > 0 )
  371.     {
  372.         if ( xIndex >= xTiles )
  373.             xIndex=xTiles;
  374.     } else {
  375.         // allow access as a singly dimensioned array
  376.         if ( xIndex >= xTiles )
  377.         {
  378.             yIndex= (xIndex / xTiles);
  379.             xIndex= (xIndex % xTiles);
  380.         }
  381.     }
  382.     viewPort.topLeft.x= tileSize.x * xIndex;
  383.     viewPort.topLeft.y= tileSize.y * yIndex;
  384.     viewPort.bottomRight.x= tileSize.x * (xIndex+1);
  385.     viewPort.bottomRight.y= tileSize.y * (yIndex+1);
  386.     viewPort &= localBounds; // just in case;
  387.     index.x=xIndex; index.y=yIndex;
  388. }
  389.