home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / a / aadraw / Source / c / tosprite < prev   
Encoding:
Text File  |  1996-10-16  |  8.6 KB  |  292 lines

  1. /* ToSprite.c */
  2.  
  3. /* Draw to Sprite routines for AADraw
  4.  * (K) All Rites Reversed - Copy What You Like (see file Copying)
  5.  *
  6.  * Authors:
  7.  *      Peter Hartley       <peter@ant.co.uk>
  8.  *
  9.  * History:
  10.  *      12-Aug-96 pdh Started
  11.  *      12-Aug-96 *** Release 1.00
  12.  *      14-Oct-96 pdh Add hourglass calls
  13.  *      14-Oct-96 *** Release 1.01
  14.  *      16-Oct-96 pdh Change to use memset rather than GFX_CLG
  15.  *
  16.  * See also:
  17.  *      http:/www.ant.co.uk/~peter/software/aadraw.htm
  18.  *
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #include "DeskLib:File.h"
  26. #include "DeskLib:Sprite.h"
  27. #include "DeskLib:Str.h"
  28. #include "DeskLib:GFX.h"
  29. #include "DeskLib:Wimp.h"
  30. #include "DeskLib:Hourglass.h"
  31.  
  32. #include "aadraw.h"
  33.  
  34.  
  35.     /*=================================*
  36.      *   Calling the DrawFile module   *
  37.      *   (adapted from ROLib_Xtra)     *
  38.      *=================================*/
  39.  
  40.  
  41. typedef struct
  42. {
  43.     int x0,y0;
  44.     int x1,y1;
  45.     int x2,y2;
  46. } draw_matrix;
  47.  
  48. os_error *DrawFile_BBox( int flags, void *pDrawfile, int drawsize,
  49.                          draw_matrix *pDM, wimp_box *pResult )
  50. {
  51.     return SWI(5,0,0x65541, flags, pDrawfile, drawsize, pDM, pResult );
  52. }
  53.  
  54. os_error *DrawFile_Render( int flags, void *pDrawfile, int drawsize,
  55.                          draw_matrix *pDM, wimp_box *pResult )
  56. {
  57.     return SWI(5,0,0x65540, flags, pDrawfile, drawsize, pDM, pResult );
  58. }
  59.  
  60. /*---------------------------------------------------------------------------*
  61.  * Add a default Netscape 216-colour palette to the given sprite (plus the   *
  62.  * nominated background colour)                                              *
  63.  *---------------------------------------------------------------------------*/
  64.  
  65. void NetscapePalette( sprite_area area, sprite s, unsigned int background )
  66. {
  67.     int *pPal;
  68.     int r,g,b;
  69.  
  70.     s->offset_next += 256*8;
  71.     s->imageoffset += 256*8;
  72.     s->maskoffset  += 256*8;
  73.     area->freeoffset += 256*8;
  74.  
  75.     pPal = (int*)(s+1);
  76.     memset( pPal, 0, 256*8 );
  77.     pPal[255*2] =
  78.         pPal[255*2+1] = background;
  79.     for ( r=0; r<6; r++ )
  80.         for ( g=0; g<6; g++ )
  81.             for ( b=0; b<6; b++ )
  82.             {
  83.                 pPal[0] =
  84.                     pPal[1] = r*0x33000000 + g*0x330000 + b*0x3300;
  85.                 pPal += 2;
  86.             }
  87. }
  88.  
  89. /*---------------------------------------------------------------------------*
  90.  * FACTOR                                                                    *
  91.  * defines how many pixels are averaged in each direction in the dither step *
  92.  *---------------------------------------------------------------------------*/
  93.  
  94. #define FACTOR 3
  95.  
  96. /*---------------------------------------------------------------------------*
  97.  * Dithering routine -- reduces by a scale of FACTOR in each direction       *
  98.  * Does sensible things with background areas so it's easy to make a true    *
  99.  * transparent GIF from the output                                           *
  100.  * Using a regular colour cube to dither into makes the code trivial         *
  101.  * (compared to what ChangeFSI must do, for instance) -- but that's still no *
  102.  * excuse for not doing Floyd-Steinberg :-(                                  *
  103.  *---------------------------------------------------------------------------*/
  104.  
  105. void Dither( sprite pSrc, sprite pDest, int w, int h, unsigned int background )
  106. {
  107.     char *srcBits  = (char*)pSrc + pSrc->imageoffset,
  108.          *destBits = (char*)pDest + pDest->imageoffset;
  109.     int x,y,i,j;
  110.     unsigned int r,g,b,t;
  111.     char byte;
  112.     char bgbyte;
  113.     int abwSrc =  (w*FACTOR + 3) & ~3;
  114.     int abwDest = (w + 3) & ~3;
  115.     char ra[256],ga[256],ba[256];
  116.     char dividebyf2[FACTOR*FACTOR*6];
  117.  
  118.     /* Precalculate divisions by 6 to speed up dither */
  119.     for (r=0; r<6; r++)
  120.         for (g=0; g<6; g++)
  121.             for (b=0; b<6; b++)
  122.             {
  123.                 ra[r*36+g*6+b] = r;
  124.                 ga[r*36+g*6+b] = g;
  125.                 ba[r*36+g*6+b] = b;
  126.             }
  127.  
  128.     /* Precalculate divisions by FACTOR*FACTOR */
  129.     for ( i=0; i < FACTOR*FACTOR*6; i++ )
  130.     {
  131.         j = (i<<8) / (FACTOR*FACTOR);
  132.         dividebyf2[i] = (j>>8) + ((j&128)?1:0);
  133.     }
  134.  
  135.     r = (background & 0xFF00)/0x33;
  136.     r = (r>>8) + ((r&128)?1:0);
  137.     g = (background & 0xFF0000)/0x3300;
  138.     g = (g>>8) + ((g&128)?1:0);
  139.     b = (background & 0xFF000000)/0x330000;
  140.     b = (b>>8) + ((b&128)?1:0);
  141.     bgbyte = b*36+g*6+r;
  142.  
  143.     for ( y=0; y < h; y++ )
  144.     {
  145.         for ( x=0; x < w; x++ )
  146.         {
  147.             r=g=b=t=0;
  148.             for (i=0; i<FACTOR; i++)
  149.                 for (j=0; j<FACTOR; j++)
  150.                 {
  151.                     byte = srcBits[x*FACTOR+i+j*abwSrc];
  152.                     if ( byte==255 )
  153.                     {
  154.                         byte=bgbyte;
  155.                         t++;
  156.                     }
  157. #if 1
  158.                     /* Not doing the divisions here speeds up the WHOLE
  159.                      * PROGRAM by a factor of 4
  160.                      */
  161.                     b += ba[byte]; g += ga[byte]; r += ra[byte];
  162. #else
  163.                     b += (byte%6)*256;  byte /= 6;
  164.                     g += (byte%6)*256;  byte /= 6;
  165.                     r += (byte%6)*256;
  166. #endif
  167.                 }
  168.             if ( t == FACTOR*FACTOR )
  169.                 destBits[x] = 255;
  170.             else
  171.             {
  172. #if 1
  173.                 /* Not doing these divisions here speeds it up by a
  174.                  * further 10%
  175.                  */
  176.                 destBits[x] = 36 * dividebyf2[r]
  177.                             +  6 * dividebyf2[g]
  178.                             +      dividebyf2[b];
  179. #else
  180.                 r = ( r /(FACTOR*FACTOR) );
  181.                 r = (r>>8) + ((r & 128)?1:0);
  182.                 g = ( g /(FACTOR*FACTOR) );
  183.                 g = (g>>8) + ((g & 128)?1:0);
  184.                 b = ( b /(FACTOR*FACTOR) );
  185.                 b = (b>>8) + ((b & 128)?1:0);
  186.                 destBits[x] = r*36+g*6+b;
  187. #endif
  188.             }
  189.         }
  190.         destBits += abwDest;
  191.         srcBits += abwSrc*FACTOR;
  192.         Hourglass_Percentage( 50 + (int)(50.0*y/h) );
  193.     }
  194. }
  195.  
  196.  
  197.     /*===============================*
  198.      *   Main DrawToSprite routine   *
  199.      *===============================*/
  200.  
  201.  
  202. sprite_area DrawToSprite( void *pDraw, int drawsize,
  203.                           unsigned int *pSpritesize, unsigned int background )
  204. {
  205.     sprite_area area, ditharea;
  206.     draw_matrix tm = { 0x10000 * FACTOR, 0, 0, 0x10000 * FACTOR, 0, 0 };
  207.     wimp_box box;
  208.     int areasize, dithareasize;
  209.     int spritex, spritey;
  210.     sprite_outputstate sos;
  211.     sprite pSprite, pDithSprite;
  212.  
  213.  
  214.     if ( DrawFile_BBox( 0, pDraw, drawsize, &tm, &box ) )
  215.     {
  216.         fprintf( stderr, "Bad Draw file\n" );
  217.         exit(1);
  218.     }
  219.  
  220.     tm.x2 = 3584-box.min.x;
  221.     tm.y2 = 3584-box.min.y;
  222.     box.min.x = box.min.x / 256;
  223.     box.max.x = box.max.x / 256;
  224.     box.min.y = box.min.y / 256;
  225.     box.max.y = box.max.y / 256;
  226.  
  227.     spritex = (box.max.x - box.min.x)/2 + 16;
  228.     spritex = ( (spritex + FACTOR - 1) /FACTOR ) * FACTOR;
  229.     spritey = (box.max.y - box.min.y)/2 + 16;
  230.     spritey = ( (spritey + FACTOR - 1) /FACTOR ) * FACTOR;
  231.  
  232.     areasize = Sprite_MemorySize( spritex,
  233.                                   spritey,
  234.                                   28, sprite_HASNOMASKPAL );
  235.     areasize += 256*8 + sizeof(sprite_areainfo);
  236.     area = malloc(areasize);
  237.     if ( !area)
  238.     {
  239.         fprintf(stderr,"Can't allocate %d-byte sprite area\n", areasize );
  240.         exit(1);
  241.     }
  242.  
  243.     area->areasize = areasize;
  244.     area->numsprites = 0;
  245.     area->firstoffset =
  246.         area->freeoffset = 16;
  247.  
  248.     Sprite_Create( area, "drawfile", FALSE, spritex, spritey, 28 );
  249.  
  250.     pSprite = (sprite)((char*)area + 16);
  251.  
  252.     NetscapePalette( area, pSprite, background );
  253.  
  254.     Hourglass_On();
  255.  
  256.     memset( ((char*)pSprite) + pSprite->imageoffset, 255,
  257.             (pSprite->width+1)*spritey*4 );
  258.  
  259.     Sprite_Redirect( area, "drawfile", NULL, &sos );
  260.         DrawFile_Render( 0, pDraw, drawsize, &tm, NULL );
  261.     Sprite_UnRedirect( &sos );
  262.  
  263.     dithareasize = Sprite_MemorySize( spritex/FACTOR, spritey/FACTOR,
  264.                                       28, sprite_HASNOMASKPAL );
  265.     dithareasize += 256*8 + sizeof( sprite_areainfo );
  266.     ditharea = malloc( dithareasize );
  267.     if ( !ditharea )
  268.     {
  269.         fprintf(stderr,"Can't allocate %d-byte sprite area (2)\n", areasize );
  270.         Hourglass_Off();
  271.         exit(1);
  272.     }
  273.  
  274.     ditharea->areasize = dithareasize;
  275.     ditharea->numsprites = 0;
  276.     ditharea->firstoffset =
  277.         ditharea->freeoffset = 16;
  278.  
  279.     Sprite_Create( ditharea, "drawfile", FALSE, spritex/FACTOR,
  280.                    spritey/FACTOR, 28 );
  281.  
  282.     pDithSprite = (sprite)((char*)ditharea + 16);
  283.  
  284.     NetscapePalette( ditharea, pDithSprite, background );
  285.  
  286.     Dither( pSprite, pDithSprite, spritex/FACTOR, spritey/FACTOR, background );
  287.  
  288.     Hourglass_Off();
  289.  
  290.     return ditharea;
  291. }
  292.