home *** CD-ROM | disk | FTP | other *** search
- /* ToSprite.c */
-
- /* Draw to Sprite routines for AADraw
- * (K) All Rites Reversed - Copy What You Like (see file Copying)
- *
- * Authors:
- * Peter Hartley <peter@ant.co.uk>
- *
- * History:
- * 12-Aug-96 pdh Started
- * 12-Aug-96 *** Release 1.00
- * 14-Oct-96 pdh Add hourglass calls
- * 14-Oct-96 *** Release 1.01
- * 16-Oct-96 pdh Change to use memset rather than GFX_CLG
- *
- * See also:
- * http:/www.ant.co.uk/~peter/software/aadraw.htm
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "DeskLib:File.h"
- #include "DeskLib:Sprite.h"
- #include "DeskLib:Str.h"
- #include "DeskLib:GFX.h"
- #include "DeskLib:Wimp.h"
- #include "DeskLib:Hourglass.h"
-
- #include "aadraw.h"
-
-
- /*=================================*
- * Calling the DrawFile module *
- * (adapted from ROLib_Xtra) *
- *=================================*/
-
-
- typedef struct
- {
- int x0,y0;
- int x1,y1;
- int x2,y2;
- } draw_matrix;
-
- os_error *DrawFile_BBox( int flags, void *pDrawfile, int drawsize,
- draw_matrix *pDM, wimp_box *pResult )
- {
- return SWI(5,0,0x65541, flags, pDrawfile, drawsize, pDM, pResult );
- }
-
- os_error *DrawFile_Render( int flags, void *pDrawfile, int drawsize,
- draw_matrix *pDM, wimp_box *pResult )
- {
- return SWI(5,0,0x65540, flags, pDrawfile, drawsize, pDM, pResult );
- }
-
- /*---------------------------------------------------------------------------*
- * Add a default Netscape 216-colour palette to the given sprite (plus the *
- * nominated background colour) *
- *---------------------------------------------------------------------------*/
-
- void NetscapePalette( sprite_area area, sprite s, unsigned int background )
- {
- int *pPal;
- int r,g,b;
-
- s->offset_next += 256*8;
- s->imageoffset += 256*8;
- s->maskoffset += 256*8;
- area->freeoffset += 256*8;
-
- pPal = (int*)(s+1);
- memset( pPal, 0, 256*8 );
- pPal[255*2] =
- pPal[255*2+1] = background;
- for ( r=0; r<6; r++ )
- for ( g=0; g<6; g++ )
- for ( b=0; b<6; b++ )
- {
- pPal[0] =
- pPal[1] = r*0x33000000 + g*0x330000 + b*0x3300;
- pPal += 2;
- }
- }
-
- /*---------------------------------------------------------------------------*
- * FACTOR *
- * defines how many pixels are averaged in each direction in the dither step *
- *---------------------------------------------------------------------------*/
-
- #define FACTOR 3
-
- /*---------------------------------------------------------------------------*
- * Dithering routine -- reduces by a scale of FACTOR in each direction *
- * Does sensible things with background areas so it's easy to make a true *
- * transparent GIF from the output *
- * Using a regular colour cube to dither into makes the code trivial *
- * (compared to what ChangeFSI must do, for instance) -- but that's still no *
- * excuse for not doing Floyd-Steinberg :-( *
- *---------------------------------------------------------------------------*/
-
- void Dither( sprite pSrc, sprite pDest, int w, int h, unsigned int background )
- {
- char *srcBits = (char*)pSrc + pSrc->imageoffset,
- *destBits = (char*)pDest + pDest->imageoffset;
- int x,y,i,j;
- unsigned int r,g,b,t;
- char byte;
- char bgbyte;
- int abwSrc = (w*FACTOR + 3) & ~3;
- int abwDest = (w + 3) & ~3;
- char ra[256],ga[256],ba[256];
- char dividebyf2[FACTOR*FACTOR*6];
-
- /* Precalculate divisions by 6 to speed up dither */
- for (r=0; r<6; r++)
- for (g=0; g<6; g++)
- for (b=0; b<6; b++)
- {
- ra[r*36+g*6+b] = r;
- ga[r*36+g*6+b] = g;
- ba[r*36+g*6+b] = b;
- }
-
- /* Precalculate divisions by FACTOR*FACTOR */
- for ( i=0; i < FACTOR*FACTOR*6; i++ )
- {
- j = (i<<8) / (FACTOR*FACTOR);
- dividebyf2[i] = (j>>8) + ((j&128)?1:0);
- }
-
- r = (background & 0xFF00)/0x33;
- r = (r>>8) + ((r&128)?1:0);
- g = (background & 0xFF0000)/0x3300;
- g = (g>>8) + ((g&128)?1:0);
- b = (background & 0xFF000000)/0x330000;
- b = (b>>8) + ((b&128)?1:0);
- bgbyte = b*36+g*6+r;
-
- for ( y=0; y < h; y++ )
- {
- for ( x=0; x < w; x++ )
- {
- r=g=b=t=0;
- for (i=0; i<FACTOR; i++)
- for (j=0; j<FACTOR; j++)
- {
- byte = srcBits[x*FACTOR+i+j*abwSrc];
- if ( byte==255 )
- {
- byte=bgbyte;
- t++;
- }
- #if 1
- /* Not doing the divisions here speeds up the WHOLE
- * PROGRAM by a factor of 4
- */
- b += ba[byte]; g += ga[byte]; r += ra[byte];
- #else
- b += (byte%6)*256; byte /= 6;
- g += (byte%6)*256; byte /= 6;
- r += (byte%6)*256;
- #endif
- }
- if ( t == FACTOR*FACTOR )
- destBits[x] = 255;
- else
- {
- #if 1
- /* Not doing these divisions here speeds it up by a
- * further 10%
- */
- destBits[x] = 36 * dividebyf2[r]
- + 6 * dividebyf2[g]
- + dividebyf2[b];
- #else
- r = ( r /(FACTOR*FACTOR) );
- r = (r>>8) + ((r & 128)?1:0);
- g = ( g /(FACTOR*FACTOR) );
- g = (g>>8) + ((g & 128)?1:0);
- b = ( b /(FACTOR*FACTOR) );
- b = (b>>8) + ((b & 128)?1:0);
- destBits[x] = r*36+g*6+b;
- #endif
- }
- }
- destBits += abwDest;
- srcBits += abwSrc*FACTOR;
- Hourglass_Percentage( 50 + (int)(50.0*y/h) );
- }
- }
-
-
- /*===============================*
- * Main DrawToSprite routine *
- *===============================*/
-
-
- sprite_area DrawToSprite( void *pDraw, int drawsize,
- unsigned int *pSpritesize, unsigned int background )
- {
- sprite_area area, ditharea;
- draw_matrix tm = { 0x10000 * FACTOR, 0, 0, 0x10000 * FACTOR, 0, 0 };
- wimp_box box;
- int areasize, dithareasize;
- int spritex, spritey;
- sprite_outputstate sos;
- sprite pSprite, pDithSprite;
-
-
- if ( DrawFile_BBox( 0, pDraw, drawsize, &tm, &box ) )
- {
- fprintf( stderr, "Bad Draw file\n" );
- exit(1);
- }
-
- tm.x2 = 3584-box.min.x;
- tm.y2 = 3584-box.min.y;
- box.min.x = box.min.x / 256;
- box.max.x = box.max.x / 256;
- box.min.y = box.min.y / 256;
- box.max.y = box.max.y / 256;
-
- spritex = (box.max.x - box.min.x)/2 + 16;
- spritex = ( (spritex + FACTOR - 1) /FACTOR ) * FACTOR;
- spritey = (box.max.y - box.min.y)/2 + 16;
- spritey = ( (spritey + FACTOR - 1) /FACTOR ) * FACTOR;
-
- areasize = Sprite_MemorySize( spritex,
- spritey,
- 28, sprite_HASNOMASKPAL );
- areasize += 256*8 + sizeof(sprite_areainfo);
- area = malloc(areasize);
- if ( !area)
- {
- fprintf(stderr,"Can't allocate %d-byte sprite area\n", areasize );
- exit(1);
- }
-
- area->areasize = areasize;
- area->numsprites = 0;
- area->firstoffset =
- area->freeoffset = 16;
-
- Sprite_Create( area, "drawfile", FALSE, spritex, spritey, 28 );
-
- pSprite = (sprite)((char*)area + 16);
-
- NetscapePalette( area, pSprite, background );
-
- Hourglass_On();
-
- memset( ((char*)pSprite) + pSprite->imageoffset, 255,
- (pSprite->width+1)*spritey*4 );
-
- Sprite_Redirect( area, "drawfile", NULL, &sos );
- DrawFile_Render( 0, pDraw, drawsize, &tm, NULL );
- Sprite_UnRedirect( &sos );
-
- dithareasize = Sprite_MemorySize( spritex/FACTOR, spritey/FACTOR,
- 28, sprite_HASNOMASKPAL );
- dithareasize += 256*8 + sizeof( sprite_areainfo );
- ditharea = malloc( dithareasize );
- if ( !ditharea )
- {
- fprintf(stderr,"Can't allocate %d-byte sprite area (2)\n", areasize );
- Hourglass_Off();
- exit(1);
- }
-
- ditharea->areasize = dithareasize;
- ditharea->numsprites = 0;
- ditharea->firstoffset =
- ditharea->freeoffset = 16;
-
- Sprite_Create( ditharea, "drawfile", FALSE, spritex/FACTOR,
- spritey/FACTOR, 28 );
-
- pDithSprite = (sprite)((char*)ditharea + 16);
-
- NetscapePalette( ditharea, pDithSprite, background );
-
- Dither( pSprite, pDithSprite, spritex/FACTOR, spritey/FACTOR, background );
-
- Hourglass_Off();
-
- return ditharea;
- }
-