home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.5 / Examples / Icon / GlowIconImage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-30  |  25.4 KB  |  1,288 lines

  1. /*
  2.  * $Id$
  3.  *
  4.  * :ts=4
  5.  *
  6.  *
  7.  * COPYRIGHT:
  8.  *
  9.  *   Unless otherwise noted, all files are Copyright (c) 1999 Amiga, Inc.
  10.  *   All rights reserved.
  11.  *
  12.  * DISCLAIMER:
  13.  *
  14.  *   This software is provided "as is". No representations or warranties
  15.  *   are made with respect to the accuracy, reliability, performance,
  16.  *   currentness, or operation of this software, and all use is at your
  17.  *   own risk. Neither Amiga nor the authors assume any responsibility
  18.  *   or liability whatsoever with respect to your use of this software.
  19.  *
  20.  */
  21.  
  22. #include <intuition/gadgetclass.h>
  23.  
  24. #include <datatypes/datatypes.h>
  25. #include <datatypes/pictureclass.h>
  26.  
  27. #include <graphics/gfxmacros.h>
  28.  
  29. #include <hardware/blit.h>
  30.  
  31. #include <exec/memory.h>
  32.  
  33. #include <dos/dosextens.h>
  34. #include <dos/rdargs.h>
  35. #include <dos/dosasl.h>
  36.  
  37. #include <clib/intuition_protos.h>
  38. #include <clib/datatypes_protos.h>
  39. #include <clib/graphics_protos.h>
  40. #include <clib/utility_protos.h>
  41. #include <clib/exec_protos.h>
  42. #include <clib/dos_protos.h>
  43. #include <clib/alib_protos.h>
  44.  
  45. #include <pragmas/intuition_pragmas.h>
  46. #include <pragmas/datatypes_pragmas.h>
  47. #include <pragmas/graphics_pragmas.h>
  48. #include <pragmas/utility_pragmas.h>
  49. #include <pragmas/exec_sysbase_pragmas.h>
  50. #include <pragmas/dos_pragmas.h>
  51.  
  52. #define USE_BUILTIN_MATH
  53. #include <string.h>
  54. #include <stdio.h>
  55.  
  56. /****************************************************************************/
  57.  
  58. typedef LONG    SWITCH;
  59. typedef STRPTR    KEY;
  60. typedef LONG *    NUMBER;
  61.  
  62. /****************************************************************************/
  63.  
  64. #define MINTERM_ZERO        0
  65. #define MINTERM_COPY        ABC | ABNC | NABC | NABNC
  66. #define MINTERM_NOT_B_AND_C    ANBC | NANBC
  67. #define MINTERM_B_OR_C        ABC | ABNC | NABC | NABNC | ANBC | NANBC
  68.  
  69. /****************************************************************************/
  70.  
  71. #define ZERO ((BPTR)0L)
  72.  
  73. /****************************************************************************/
  74.  
  75. #define FIB_IS_FILE(fib)    ((fib)->fib_DirEntryType < 0)
  76. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType >= 0 && (fib)->fib_DirEntryType != ST_SOFTLINK)
  77.  
  78. /****************************************************************************/
  79.  
  80. #define OK (0)
  81. #define SAME (0)
  82. #define CANNOT !
  83.  
  84. /****************************************************************************/
  85.  
  86. const STRPTR GlowSuffix = ".glow";
  87. const STRPTR PadSuffix = ".pad";
  88. const int MatchLen = 512;
  89.  
  90. /****************************************************************************/
  91.  
  92. extern struct Library * SysBase;
  93. extern struct Library * DOSBase;
  94. extern struct Library * IntuitionBase;
  95. extern struct Library * GfxBase;
  96. extern struct Library * UtilityBase;
  97. extern struct Library * DataTypesBase;
  98.  
  99. /****************************************************************************/
  100.  
  101. #define MM 2147483647    /* a Mersenne prime */
  102. #define AA 48271        /* this does well in the spectral test */
  103. #define QQ 44488        /* (long)(MM/AA) */
  104. #define RR 3399            /* MM % AA; it is important that RR < QQ */
  105.  
  106. STATIC LONG X;
  107.  
  108. VOID
  109. SetRandomSeed(LONG seed)
  110. {
  111.     X = (seed % MM);
  112. }
  113.  
  114. LONG
  115. Random(LONG maxValue)
  116. {
  117.     X = AA * (X % QQ) - RR * (LONG)(X / QQ);
  118.     if(X < 0)
  119.         X += MM;
  120.  
  121.     return(X % maxValue);
  122. }
  123.  
  124. /****************************************************************************/
  125.  
  126. VOID
  127. SafeBltBitMap(
  128.     struct BitMap * src,LONG srcX,LONG srcY,
  129.     struct BitMap * dst,LONG dstX,LONG dstY,
  130.     LONG width,LONG height,
  131.     LONG minTerm,LONG mask)
  132. {
  133.     LONG dstWidth,dstHeight;
  134.  
  135.     dstWidth    = GetBitMapAttr(dst,BMA_WIDTH);
  136.     dstHeight    = GetBitMapAttr(dst,BMA_HEIGHT);
  137.  
  138.     if(dstX + width > dstWidth)
  139.         width = dstWidth - dstX;
  140.  
  141.     if(dstY + height > dstHeight)
  142.         height = dstHeight - dstY;
  143.  
  144.     if(0 <= dstX && dstX < dstWidth &&
  145.        0 <= dstY && dstY < dstHeight &&
  146.        width > 0 &&
  147.        height > 0)
  148.     {
  149.         LONG dstMask = (1UL << GetBitMapAttr(dst,BMA_DEPTH)) - 1;
  150.  
  151.         BltBitMap(src,srcX,srcY,dst,dstX,dstY,width,height,minTerm,mask & dstMask,NULL);
  152.     }
  153. }
  154.  
  155. /****************************************************************************/
  156.  
  157. VOID
  158. DeleteBitMap(struct BitMap * bm)
  159. {
  160.     if(bm != NULL)
  161.     {
  162.         LONG i;
  163.  
  164.         WaitBlit();
  165.  
  166.         for(i = 0 ; i < bm->Depth ; i++)
  167.             FreeVec(bm->Planes[i]);
  168.  
  169.         FreeVec(bm);
  170.     }
  171. }
  172.  
  173. struct BitMap *
  174. CreateBitMap(LONG depth,LONG width,LONG height)
  175. {
  176.     struct BitMap * result = NULL;
  177.     struct BitMap * bm;
  178.     LONG i,bytesPerPlane;
  179.  
  180.     bm = AllocVec(sizeof(*bm),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  181.     if(bm == NULL)
  182.         goto out;
  183.  
  184.     InitBitMap(bm,depth,width,height);
  185.  
  186.     bytesPerPlane = bm->BytesPerRow * bm->Rows;
  187.  
  188.     for(i = 0 ; i < bm->Depth ; i++)
  189.     {
  190.         bm->Planes[i] = AllocVec(bytesPerPlane,MEMF_PUBLIC|MEMF_CHIP);
  191.         if(bm->Planes[i] == NULL)
  192.             goto out;
  193.     }
  194.  
  195.     SafeBltBitMap(bm,0,0,bm,0,0,bm->BytesPerRow * 8,bm->Rows,MINTERM_ZERO,0xFF);
  196.  
  197.     result = bm;
  198.  
  199.  out:
  200.  
  201.     if(result == NULL)
  202.         DeleteBitMap(bm);
  203.  
  204.     return(result);
  205. }
  206.  
  207. /****************************************************************************/
  208.  
  209. struct BitMap *
  210. CreateOutlineBitMap(struct BitMap * source)
  211. {
  212.     struct BitMap * result = NULL;
  213.     struct BitMap * mask = NULL;
  214.     struct BitMap * bm;
  215.     LONG width,height;
  216.     LONG i;
  217.  
  218.     width    = GetBitMapAttr(source,BMA_WIDTH);
  219.     height    = GetBitMapAttr(source,BMA_HEIGHT);
  220.  
  221.     bm = CreateBitMap(1,1 + width + 1,1 + height + 1);
  222.     if(bm == NULL)
  223.         goto out;
  224.  
  225.     mask = CreateBitMap(1,width,height);
  226.     if(mask == NULL)
  227.         goto out;
  228.  
  229.     mask->Depth = 8;
  230.     for(i = 1 ; i < 8 ; i++)
  231.         mask->Planes[i] = mask->Planes[0];
  232.  
  233.     SafeBltBitMap(source,0,0,mask,0,0,width,height,MINTERM_B_OR_C,0xFF);
  234.  
  235.     mask->Depth = 1;
  236.  
  237.     SafeBltBitMap(mask,0,0,bm,0,1,width,height,MINTERM_B_OR_C,0xFF);
  238.     SafeBltBitMap(mask,0,0,bm,2,1,width,height,MINTERM_B_OR_C,0xFF);
  239.     SafeBltBitMap(mask,0,0,bm,1,0,width,height,MINTERM_B_OR_C,0xFF);
  240.     SafeBltBitMap(mask,0,0,bm,1,2,width,height,MINTERM_B_OR_C,0xFF);
  241.  
  242.     SafeBltBitMap(mask,0,0,bm,1,1,width,height,MINTERM_NOT_B_AND_C,0xFF);
  243.  
  244.     result = bm;
  245.  
  246.  out:
  247.  
  248.     if(result == NULL)
  249.         DeleteBitMap(bm);
  250.  
  251.     DeleteBitMap(mask);
  252.  
  253.     return(result);
  254. }
  255.  
  256. /****************************************************************************/
  257.  
  258. BOOL
  259. ComposeBitMap(struct BitMap * source,struct BitMap * destination,LONG left,LONG top)
  260. {
  261.     struct BitMap * mask;
  262.     BOOL result = FALSE;
  263.     LONG width,height;
  264.     LONG i;
  265.  
  266.     width    = GetBitMapAttr(source,BMA_WIDTH);
  267.     height    = GetBitMapAttr(source,BMA_HEIGHT);
  268.  
  269.     mask = CreateBitMap(1,width,height);
  270.     if(mask == NULL)
  271.         goto out;
  272.  
  273.     mask->Depth = 8;
  274.     for(i = 1 ; i < 8 ; i++)
  275.         mask->Planes[i] = mask->Planes[0];
  276.  
  277.     SafeBltBitMap(source,0,0,mask,0,0,width,height,MINTERM_B_OR_C,0xFF);
  278.  
  279.     SafeBltBitMap(mask,0,0,destination,left,top,width,height,MINTERM_NOT_B_AND_C,0xFF);
  280.     SafeBltBitMap(source,0,0,destination,left,top,width,height,MINTERM_B_OR_C,0xFF);
  281.  
  282.     mask->Depth = 1;
  283.  
  284.     result = TRUE;
  285.  
  286.  out:
  287.  
  288.     DeleteBitMap(mask);
  289.  
  290.     return(result);
  291. }
  292.  
  293. /****************************************************************************/
  294.  
  295. BOOL
  296. ColourBitMap(struct BitMap * source,LONG colour,struct BitMap * destination,LONG left,LONG top)
  297. {
  298.     struct BitMap * mask;
  299.     BOOL result = FALSE;
  300.     struct BitMap single;
  301.     LONG width,height;
  302.     LONG i;
  303.  
  304.     width    = GetBitMapAttr(source,BMA_WIDTH);
  305.     height    = GetBitMapAttr(source,BMA_HEIGHT);
  306.  
  307.     single = (*source);
  308.     single.Depth = 8;
  309.     for(i = 1 ; i < 8 ; i++)
  310.         single.Planes[i] = single.Planes[0];
  311.  
  312.     mask = CreateBitMap(1,width,height);
  313.     if(mask == NULL)
  314.         goto out;
  315.  
  316.     mask->Depth = 8;
  317.     for(i = 1 ; i < 8 ; i++)
  318.         mask->Planes[i] = mask->Planes[0];
  319.  
  320.     SafeBltBitMap(source,0,0,mask,0,0,width,height,MINTERM_B_OR_C,0xFF);
  321.  
  322.     SafeBltBitMap(mask,0,0,destination,left,top,width,height,MINTERM_NOT_B_AND_C,0xFF);
  323.     SafeBltBitMap(&single,0,0,destination,left,top,width,height,MINTERM_B_OR_C,colour);
  324.  
  325.     mask->Depth = 1;
  326.  
  327.     result = TRUE;
  328.  
  329.  out:
  330.  
  331.     DeleteBitMap(mask);
  332.  
  333.     return(result);
  334. }
  335.  
  336. /****************************************************************************/
  337.  
  338. LONG
  339. FindBestMatch(struct ColorRegister * cmap,LONG numColours,LONG r,LONG g,LONG b)
  340. {
  341.     LONG bestPen;
  342.     LONG bestDelta;
  343.     LONG pen;
  344.     LONG delta;
  345.  
  346.     bestPen = 0;
  347.     bestDelta = 0;
  348.  
  349.     for(pen = 1 ; pen < numColours ; pen++)
  350.     {
  351.         delta = abs((int)cmap[pen].red - r) + abs((int)cmap[pen].green - g) + abs((int)cmap[pen].blue - b);
  352.         if(pen == 1 || delta < bestDelta)
  353.         {
  354.             bestDelta = delta;
  355.             bestPen = pen;
  356.         }
  357.     }
  358.  
  359.     return(bestPen);
  360. }
  361.  
  362. /****************************************************************************/
  363.  
  364. struct RGBDelta
  365. {
  366.     LONG red;
  367.     LONG green;
  368.     LONG blue;
  369. };
  370.  
  371. /****************************************************************************/
  372.  
  373. STATIC int __inline
  374. clamp(int x)
  375. {
  376.     if (x < 0)
  377.         return(0);
  378.     else if (x > 255)
  379.         return(255);
  380.     else
  381.         return(x);
  382. }
  383.  
  384. /****************************************************************************/
  385.  
  386. VOID
  387. AddGlow(STRPTR fileName,STRPTR nameBuffer,STRPTR to,BOOL dither,LONG darken)
  388. {
  389.     STATIC UWORD CheckPattern[2] =
  390.     {
  391.         0x5555,
  392.         0xAAAA
  393.     };
  394.  
  395.     struct dtFrameBox dtf;
  396.     struct FrameInfo fri;
  397.     struct BitMapHeader * bmh;
  398.     struct BitMapHeader * bmh2;
  399.     ULONG modeID;
  400.     struct gpLayout gpl;
  401.     struct BitMap * srcBitMap;
  402.     struct BitMap * dstBitMap = NULL;
  403.     struct BitMap * bm1 = NULL;
  404.     struct BitMap * bm2 = NULL;
  405.     struct BitMap * outline1 = NULL;
  406.     struct BitMap * outline2 = NULL;
  407.     struct BitMap * outline3 = NULL;
  408.     struct BitMap * outline4 = NULL;
  409.     LONG dstBitMapWidth;
  410.     LONG dstBitMapHeight;
  411.     struct ColorRegister * cmap;
  412.     struct ColorRegister * cmap2;
  413.     ULONG * cregs;
  414.     ULONG * cregs2;
  415.     LONG numColours;
  416.     Object * obj;
  417.     Object * out = NULL;
  418.     LONG error = OK;
  419.     struct RastPort rp;
  420.     LONG x,y;
  421.     LONG pen;
  422.     BPTR file = ZERO;
  423.     LONG r,g,b;
  424.     LONG r2,g2,b2;
  425.     int white,yellow,brightOrange;
  426.     struct RGBDelta * rows[2];
  427.     struct RGBDelta * row1;
  428.     struct RGBDelta * row2;
  429.     struct RGBDelta * swap;
  430.  
  431.     memset(rows,0,sizeof(rows));
  432.  
  433.     Printf("Checking file \"%s\"... ",fileName);
  434.     Flush(Output());
  435.  
  436.     obj = NewDTObject(fileName,
  437.         DTA_SourceType,    DTST_FILE,
  438.         DTA_GroupID,    GID_PICTURE,
  439.         PDTA_Remap,        FALSE,
  440.     TAG_DONE);
  441.     if(obj == NULL)
  442.     {
  443.         error = IoErr();
  444.         goto out;
  445.     }
  446.  
  447.     memset(&dtf,0,sizeof(dtf));
  448.  
  449.     memset(&fri,0,sizeof(fri));
  450.  
  451.     dtf.MethodID            = DTM_FRAMEBOX;
  452.     dtf.dtf_FrameInfo        = &fri;
  453.     dtf.dtf_ContentsInfo    = &fri;
  454.     dtf.dtf_SizeFrameInfo    = sizeof(fri);
  455.  
  456.     if(CANNOT DoMethodA(obj,(Msg)&dtf))
  457.     {
  458.         Printf("could not frame object\n");
  459.         error = -1;
  460.         goto out;
  461.     }
  462.  
  463.     if(fri.fri_Dimensions.Depth < 1 || fri.fri_Dimensions.Depth > 8)
  464.     {
  465.         Printf("unsupported depth (%ld)\n",fri.fri_Dimensions.Depth);
  466.         error = -1;
  467.         goto out;
  468.     }
  469.  
  470.     if((fri.fri_PropertyFlags & DIPF_IS_HAM) ||
  471.        (fri.fri_PropertyFlags & DIPF_IS_EXTRAHALFBRITE))
  472.     {
  473.         Printf("cannot handle HAM/Extra Halfbrite\n");
  474.         error = -1;
  475.         goto out;
  476.     }
  477.  
  478.     memset(&gpl,0,sizeof(gpl));
  479.  
  480.     gpl.MethodID    = DTM_PROCLAYOUT;
  481.     gpl.gpl_GInfo    = NULL;
  482.     gpl.gpl_Initial    = 1;
  483.  
  484.     if(CANNOT DoMethodA(obj,(Msg)&gpl))
  485.     {
  486.         Printf("could not layout object\n");
  487.         error = -1;
  488.         goto out;
  489.     }
  490.  
  491.     modeID = INVALID_ID;
  492.     cregs = NULL;
  493.     numColours = 0;
  494.     bmh = NULL;
  495.     srcBitMap = NULL;
  496.     cmap = NULL;
  497.  
  498.     GetDTAttrs(obj,
  499.         PDTA_ModeID,        &modeID,
  500.         PDTA_CRegs,            &cregs,
  501.         PDTA_NumColors,        &numColours,
  502.         PDTA_ColorRegisters,&cmap,
  503.         PDTA_BitMapHeader,    &bmh,
  504.         PDTA_BitMap,        &srcBitMap,
  505.     TAG_DONE);
  506.  
  507.     if(modeID == INVALID_ID || cregs == NULL || numColours == 0 || bmh == NULL || srcBitMap == NULL || cmap == NULL)
  508.     {
  509.         error = ERROR_REQUIRED_ARG_MISSING;
  510.         goto out;
  511.     }
  512.  
  513.     dstBitMapWidth    = 4 + bmh->bmh_Width + 4;
  514.     dstBitMapHeight    = 4 + bmh->bmh_Height + 4;
  515.  
  516.     dstBitMap = CreateBitMap(bmh->bmh_Depth,dstBitMapWidth,dstBitMapHeight);
  517.     if(dstBitMap == NULL)
  518.     {
  519.         error = ERROR_NO_FREE_STORE;
  520.         goto out;
  521.     }
  522.  
  523.     rows[0] = AllocVec(sizeof(*rows[0]) * (2 + dstBitMapWidth),MEMF_ANY|MEMF_CLEAR);
  524.     rows[1] = AllocVec(sizeof(*rows[1]) * (2 + dstBitMapWidth),MEMF_ANY|MEMF_CLEAR);
  525.  
  526.     if(rows[0] == NULL || rows[1] == NULL)
  527.     {
  528.         error = ERROR_NO_FREE_STORE;
  529.         goto out;
  530.     }
  531.  
  532.     row1 = rows[0] + 1;
  533.     row2 = rows[1] + 1;
  534.  
  535.     bm1 = CreateBitMap(bmh->bmh_Depth,dstBitMapWidth,dstBitMapHeight);
  536.     if(bm1 == NULL)
  537.     {
  538.         error = ERROR_NO_FREE_STORE;
  539.         goto out;
  540.     }
  541.  
  542.     bm2 = AllocBitMap(dstBitMapWidth,dstBitMapHeight,bmh->bmh_Depth,BMF_CLEAR,NULL);
  543.     if(bm2 == NULL)
  544.     {
  545.         error = ERROR_NO_FREE_STORE;
  546.         goto out;
  547.     }
  548.  
  549.     SafeBltBitMap(srcBitMap,0,0,dstBitMap,4,4,bmh->bmh_Width,bmh->bmh_Width,MINTERM_COPY,0xFF);
  550.  
  551.     InitRastPort(&rp);
  552.     rp.BitMap = dstBitMap;
  553.     SetABPenDrMd(&rp,0,0,JAM2);
  554.  
  555.     if(dither)
  556.     {
  557.         Printf("dithering... ");
  558.         Flush(Output());
  559.  
  560.         for(x = 0 ; x < bmh->bmh_Width ; x++)
  561.         {
  562.             row1[x].red        = Random(127) - 63;
  563.             row1[x].green    = Random(127) - 63;
  564.             row1[x].blue    = Random(127) - 63;
  565.         }
  566.  
  567.         for(y = 0 ; y < bmh->bmh_Height ; y++)
  568.         {
  569.             if((y % 2) == 0)
  570.             {
  571.                 for(x = 0 ; x < bmh->bmh_Width ; x++)
  572.                 {
  573.                     pen = ReadPixel(&rp,x+4,y+4);
  574.                     if(pen != 0)
  575.                     {
  576.                         r = cmap[pen].red;
  577.                         g = cmap[pen].green;
  578.                         b = cmap[pen].blue;
  579.     
  580.                         r = clamp(max(0,r - darken) + row1[x].red    / 16);
  581.                         g = clamp(max(0,g - darken) + row1[x].green    / 16);
  582.                         b = clamp(max(0,b - darken) + row1[x].blue    / 16);
  583.     
  584.                         pen = FindBestMatch(cmap,numColours,r,g,b);
  585.     
  586.                         SetAPen(&rp,pen);
  587.                         WritePixel(&rp,x+4,y+4);
  588.     
  589.                         r2 = cmap[pen].red;
  590.                         g2 = cmap[pen].green;
  591.                         b2 = cmap[pen].blue;
  592.  
  593.                         row1[x+1].red    += (r - r2) * 7;
  594.                         row1[x+1].green    += (g - g2) * 7;
  595.                         row1[x+1].blue    += (b - b2) * 7;
  596.     
  597.                         row2[x-1].red    += (r - r2) * 3;
  598.                         row2[x-1].green    += (g - g2) * 3;
  599.                         row2[x-1].blue    += (b - b2) * 3;
  600.     
  601.                         row2[x  ].red    += (r - r2) * 5;
  602.                         row2[x  ].green    += (g - g2) * 5;
  603.                         row2[x  ].blue    += (b - b2) * 5;
  604.     
  605.                         row2[x+1].red    += (r - r2);
  606.                         row2[x+1].green    += (g - g2);
  607.                         row2[x+1].blue    += (b - b2);
  608.                     }
  609.                 }
  610.             }
  611.             else
  612.             {
  613.                 for(x = bmh->bmh_Width - 1 ; x >= 0 ; x--)
  614.                 {
  615.                     pen = ReadPixel(&rp,x+4,y+4);
  616.                     if(pen != 0)
  617.                     {
  618.                         r = cmap[pen].red;
  619.                         g = cmap[pen].green;
  620.                         b = cmap[pen].blue;
  621.     
  622.                         r = clamp(max(0,r - darken) + row1[x].red    / 16);
  623.                         g = clamp(max(0,g - darken) + row1[x].green    / 16);
  624.                         b = clamp(max(0,b - darken) + row1[x].blue    / 16);
  625.     
  626.                         pen = FindBestMatch(cmap,numColours,r,g,b);
  627.     
  628.                         SetAPen(&rp,pen);
  629.                         WritePixel(&rp,x+4,y+4);
  630.     
  631.                         r2 = cmap[pen].red;
  632.                         g2 = cmap[pen].green;
  633.                         b2 = cmap[pen].blue;
  634.     
  635.                         row1[x-1].red    += (r - r2) * 7;
  636.                         row1[x-1].green    += (g - g2) * 7;
  637.                         row1[x-1].blue    += (b - b2) * 7;
  638.     
  639.                         row2[x+1].red    += (r - r2) * 3;
  640.                         row2[x+1].green    += (g - g2) * 3;
  641.                         row2[x+1].blue    += (b - b2) * 3;
  642.     
  643.                         row2[x  ].red    += (r - r2) * 5;
  644.                         row2[x  ].green    += (g - g2) * 5;
  645.                         row2[x  ].blue    += (b - b2) * 5;
  646.     
  647.                         row2[x-1].red    += (r - r2);
  648.                         row2[x-1].green    += (g - g2);
  649.                         row2[x-1].blue    += (b - b2);
  650.                     }
  651.                 }
  652.             }
  653.  
  654.             swap = row1;
  655.             row1 = row2;
  656.             row2 = swap;
  657.  
  658.             memset(row2,0,sizeof(*row2) * dstBitMapWidth);
  659.         }
  660.     }
  661.     else
  662.     {
  663.         Printf("remapping... ");
  664.         Flush(Output());
  665.  
  666.         for(y = 0 ; y < bmh->bmh_Height ; y++)
  667.         {
  668.             for(x = 0 ; x < bmh->bmh_Width ; x++)
  669.             {
  670.                 pen = ReadPixel(&rp,x+4,y+4);
  671.                 if(pen != 0)
  672.                 {
  673.                     r = cmap[pen].red;
  674.                     g = cmap[pen].green;
  675.                     b = cmap[pen].blue;
  676.  
  677.                     r = max(0,r - darken);
  678.                     g = max(0,g - darken);
  679.                     b = max(0,b - darken);
  680.  
  681.                     pen = FindBestMatch(cmap,numColours,r,g,b);
  682.  
  683.                     SetAPen(&rp,pen);
  684.                     WritePixel(&rp,x+4,y+4);
  685.                 }
  686.             }
  687.         }
  688.     }
  689.  
  690.     Printf("making outlines... ");
  691.     Flush(Output());
  692.  
  693.     outline1 = CreateOutlineBitMap(srcBitMap);    /* 1+1 */
  694.     if(outline1 == NULL)
  695.     {
  696.         error = ERROR_NO_FREE_STORE;
  697.         goto out;
  698.     }
  699.  
  700.     outline2 = CreateOutlineBitMap(outline1);    /* 2+2 */
  701.     if(outline2 == NULL)
  702.     {
  703.         error = ERROR_NO_FREE_STORE;
  704.         goto out;
  705.     }
  706.  
  707.     outline3 = CreateOutlineBitMap(outline2);    /* 3+3 */
  708.     if(outline3 == NULL)
  709.     {
  710.         error = ERROR_NO_FREE_STORE;
  711.         goto out;
  712.     }
  713.  
  714.     outline4 = CreateOutlineBitMap(outline3);    /* 4+4 */
  715.     if(outline4 == NULL)
  716.     {
  717.         error = ERROR_NO_FREE_STORE;
  718.         goto out;
  719.     }
  720.  
  721.     SetAfPt(&rp,CheckPattern,1);
  722.     rp.BitMap = outline4;
  723.     SetABPenDrMd(&rp,0,0,JAM1);
  724.  
  725.     RectFill(&rp,0,0,(4+bmh->bmh_Width+4)-1,(4+bmh->bmh_Height+4)-1);
  726.  
  727.     Printf("composing... ");
  728.     Flush(Output());
  729.  
  730.     white            = FindBestMatch(cmap,numColours,0xFF,0xFF,0xFF);
  731.     yellow            = FindBestMatch(cmap,numColours,0xEF,0xE7,0x14);
  732.     brightOrange    = FindBestMatch(cmap,numColours,0xDF,0xBA,0x45);
  733.  
  734.     if(CANNOT ColourBitMap(outline4,brightOrange,bm1,0,0))
  735.     {
  736.         error = ERROR_NO_FREE_STORE;
  737.         goto out;
  738.     }
  739.  
  740.     if(CANNOT ColourBitMap(outline3,brightOrange,bm1,1,1))
  741.     {
  742.         error = ERROR_NO_FREE_STORE;
  743.         goto out;
  744.     }
  745.  
  746.     if(CANNOT ColourBitMap(outline2,yellow,bm1,2,2))
  747.     {
  748.         error = ERROR_NO_FREE_STORE;
  749.         goto out;
  750.     }
  751.  
  752.     if(CANNOT ColourBitMap(outline1,white,bm1,3,3))
  753.     {
  754.         error = ERROR_NO_FREE_STORE;
  755.         goto out;
  756.     }
  757.  
  758.     if(CANNOT ComposeBitMap(dstBitMap,bm1,0,0))
  759.     {
  760.         error = ERROR_NO_FREE_STORE;
  761.         goto out;
  762.     }
  763.  
  764.     WaitBlit();
  765.  
  766.     Printf("creating picture... ");
  767.     Flush(Output());
  768.  
  769.     out = NewDTObject(FilePart(fileName),
  770.         DTA_SourceType,        DTST_RAM,
  771.         DTA_GroupID,        GID_PICTURE,
  772.         PDTA_NumColors,        numColours,
  773.         PDTA_BitMap,        bm2,
  774.         PDTA_ModeID,        modeID,
  775.     TAG_DONE);
  776.     if(out == NULL)
  777.     {
  778.         error = IoErr();
  779.         goto out;
  780.     }
  781.  
  782.     SafeBltBitMap(bm1,0,0,bm2,0,0,dstBitMapWidth,dstBitMapHeight,MINTERM_COPY,0xFF);
  783.     WaitBlit();
  784.  
  785.     bm2 = NULL;
  786.  
  787.     if(GetDTAttrs(out,
  788.         PDTA_BitMapHeader,        &bmh2,
  789.         PDTA_ColorRegisters,    &cmap2,
  790.         PDTA_CRegs,                &cregs2,
  791.     TAG_DONE) != 3)
  792.     {
  793.         error = ERROR_REQUIRED_ARG_MISSING;
  794.         goto out;
  795.     }
  796.  
  797.     memset(bmh2,0,sizeof(*bmh2));
  798.  
  799.     bmh2->bmh_Left            = bmh->bmh_Left;
  800.     bmh2->bmh_Top            = bmh->bmh_Top;
  801.     bmh2->bmh_Width            = dstBitMapWidth;
  802.     bmh2->bmh_Height        = dstBitMapHeight;
  803.     bmh2->bmh_Depth            = bmh->bmh_Depth;
  804.     bmh2->bmh_PageWidth        = max(bmh2->bmh_Width,bmh->bmh_PageWidth);
  805.     bmh2->bmh_PageHeight    = max(bmh2->bmh_Height,bmh->bmh_PageHeight);
  806.     bmh2->bmh_Transparent    = 0;
  807.     bmh2->bmh_Masking        = mskHasTransparentColor;
  808.     bmh2->bmh_XAspect        = 1;
  809.     bmh2->bmh_YAspect        = 1;
  810.  
  811.     memcpy(cregs2,cregs,numColours * 3 * sizeof(ULONG));
  812.     memcpy(cmap2,cmap,numColours * sizeof(*cmap));
  813.  
  814.     if(to != NULL)
  815.     {
  816.         strcpy(nameBuffer,to);
  817.         AddPart(nameBuffer,FilePart(fileName),MatchLen);
  818.         strcat(nameBuffer,GlowSuffix);
  819.     }
  820.     else
  821.     {
  822.         strcpy(nameBuffer,fileName);
  823.         strcat(nameBuffer,GlowSuffix);
  824.     }
  825.  
  826.     Printf("writing file \"%s\"... ",nameBuffer);
  827.     Flush(Output());
  828.  
  829.     file = Open(nameBuffer,MODE_NEWFILE);
  830.     if(file == ZERO)
  831.     {
  832.         error = IoErr();
  833.         goto out;
  834.     }
  835.  
  836.     if(CANNOT DoMethod(out,DTM_WRITE,NULL,file,DTWM_IFF,NULL))
  837.     {
  838.         error = IoErr();
  839.         Close(file);
  840.         file = ZERO;
  841.         DeleteFile(nameBuffer);
  842.         goto out;
  843.     }
  844.  
  845.  out:
  846.  
  847.     FreeVec(rows[0]);
  848.     FreeVec(rows[1]);
  849.  
  850.     if(file != ZERO)
  851.         Close(file);
  852.  
  853.     FreeBitMap(bm2);
  854.  
  855.     DeleteBitMap(outline1);
  856.     DeleteBitMap(outline2);
  857.     DeleteBitMap(outline3);
  858.     DeleteBitMap(outline4);
  859.  
  860.     DeleteBitMap(dstBitMap);
  861.     DeleteBitMap(bm1);
  862.  
  863.     DisposeDTObject(obj);
  864.     DisposeDTObject(out);
  865.  
  866.     if(error != -1)
  867.     {
  868.         if(error == OK)
  869.         {
  870.             Printf("Ok\n");
  871.         }
  872.         else
  873.         {
  874.             if(error < 2000)
  875.             {
  876.                 UBYTE buffer[100];
  877.  
  878.                 Fault(error,NULL,buffer,sizeof(buffer));
  879.                 Printf("%s\n",buffer);
  880.             }
  881.             else
  882.             {
  883.                 Printf("%s\n",GetDTString(error));
  884.             }
  885.         }
  886.     }
  887. }
  888.  
  889. /****************************************************************************/
  890.  
  891. VOID
  892. AddPadding(STRPTR fileName,STRPTR nameBuffer,STRPTR to)
  893. {
  894.     struct dtFrameBox dtf;
  895.     struct FrameInfo fri;
  896.     struct BitMapHeader * bmh;
  897.     struct BitMapHeader * bmh2;
  898.     ULONG modeID;
  899.     struct gpLayout gpl;
  900.     struct BitMap * srcBitMap;
  901.     struct BitMap * dstBitMap = NULL;
  902.     LONG dstBitMapWidth;
  903.     LONG dstBitMapHeight;
  904.     struct ColorRegister * cmap;
  905.     struct ColorRegister * cmap2;
  906.     ULONG * cregs;
  907.     ULONG * cregs2;
  908.     LONG numColours;
  909.     Object * obj;
  910.     Object * out = NULL;
  911.     LONG error = OK;
  912.     BPTR file = ZERO;
  913.  
  914.     Printf("Checking file \"%s\"... ",fileName);
  915.     Flush(Output());
  916.  
  917.     obj = NewDTObject(fileName,
  918.         DTA_SourceType,    DTST_FILE,
  919.         DTA_GroupID,    GID_PICTURE,
  920.         PDTA_Remap,        FALSE,
  921.     TAG_DONE);
  922.     if(obj == NULL)
  923.     {
  924.         error = IoErr();
  925.         goto out;
  926.     }
  927.  
  928.     memset(&dtf,0,sizeof(dtf));
  929.  
  930.     memset(&fri,0,sizeof(fri));
  931.  
  932.     dtf.MethodID            = DTM_FRAMEBOX;
  933.     dtf.dtf_FrameInfo        = &fri;
  934.     dtf.dtf_ContentsInfo    = &fri;
  935.     dtf.dtf_SizeFrameInfo    = sizeof(fri);
  936.  
  937.     if(CANNOT DoMethodA(obj,(Msg)&dtf))
  938.     {
  939.         Printf("could not frame object\n");
  940.         error = -1;
  941.         goto out;
  942.     }
  943.  
  944.     if(fri.fri_Dimensions.Depth < 1 || fri.fri_Dimensions.Depth > 8)
  945.     {
  946.         Printf("unsupported depth (%ld)\n",fri.fri_Dimensions.Depth);
  947.         error = -1;
  948.         goto out;
  949.     }
  950.  
  951.     if((fri.fri_PropertyFlags & DIPF_IS_HAM) ||
  952.        (fri.fri_PropertyFlags & DIPF_IS_EXTRAHALFBRITE))
  953.     {
  954.         Printf("cannot handle HAM/Extra Halfbrite\n");
  955.         error = -1;
  956.         goto out;
  957.     }
  958.  
  959.     memset(&gpl,0,sizeof(gpl));
  960.  
  961.     gpl.MethodID    = DTM_PROCLAYOUT;
  962.     gpl.gpl_GInfo    = NULL;
  963.     gpl.gpl_Initial    = 1;
  964.  
  965.     if(CANNOT DoMethodA(obj,(Msg)&gpl))
  966.     {
  967.         Printf("could not layout object\n");
  968.         error = -1;
  969.         goto out;
  970.     }
  971.  
  972.     modeID = INVALID_ID;
  973.     cregs = NULL;
  974.     numColours = 0;
  975.     bmh = NULL;
  976.     srcBitMap = NULL;
  977.     cmap = NULL;
  978.  
  979.     GetDTAttrs(obj,
  980.         PDTA_ModeID,        &modeID,
  981.         PDTA_CRegs,            &cregs,
  982.         PDTA_NumColors,        &numColours,
  983.         PDTA_ColorRegisters,&cmap,
  984.         PDTA_BitMapHeader,    &bmh,
  985.         PDTA_BitMap,        &srcBitMap,
  986.     TAG_DONE);
  987.  
  988.     if(modeID == INVALID_ID || cregs == NULL || numColours == 0 || bmh == NULL || srcBitMap == NULL || cmap == NULL)
  989.     {
  990.         error = ERROR_REQUIRED_ARG_MISSING;
  991.         goto out;
  992.     }
  993.  
  994.     dstBitMapWidth    = 4 + bmh->bmh_Width + 4;
  995.     dstBitMapHeight    = 4 + bmh->bmh_Height + 4;
  996.  
  997.     dstBitMap = AllocBitMap(dstBitMapWidth,dstBitMapHeight,bmh->bmh_Depth,BMF_CLEAR,NULL);
  998.     if(dstBitMap == NULL)
  999.     {
  1000.         error = ERROR_NO_FREE_STORE;
  1001.         goto out;
  1002.     }
  1003.  
  1004.     Printf("padding... ");
  1005.     Flush(Output());
  1006.  
  1007.     SafeBltBitMap(srcBitMap,0,0,dstBitMap,4,4,bmh->bmh_Width,bmh->bmh_Width,MINTERM_COPY,0xFF);
  1008.     WaitBlit();
  1009.  
  1010.     Printf("creating picture... ");
  1011.     Flush(Output());
  1012.  
  1013.     out = NewDTObject(FilePart(fileName),
  1014.         DTA_SourceType,        DTST_RAM,
  1015.         DTA_GroupID,        GID_PICTURE,
  1016.         PDTA_NumColors,        numColours,
  1017.         PDTA_BitMap,        dstBitMap,
  1018.         PDTA_ModeID,        modeID,
  1019.     TAG_DONE);
  1020.     if(out == NULL)
  1021.     {
  1022.         error = IoErr();
  1023.         goto out;
  1024.     }
  1025.  
  1026.     dstBitMap = NULL;
  1027.  
  1028.     if(GetDTAttrs(out,
  1029.         PDTA_BitMapHeader,        &bmh2,
  1030.         PDTA_ColorRegisters,    &cmap2,
  1031.         PDTA_CRegs,                &cregs2,
  1032.     TAG_DONE) != 3)
  1033.     {
  1034.         error = ERROR_REQUIRED_ARG_MISSING;
  1035.         goto out;
  1036.     }
  1037.  
  1038.     memset(bmh2,0,sizeof(*bmh2));
  1039.  
  1040.     bmh2->bmh_Left            = bmh->bmh_Left;
  1041.     bmh2->bmh_Top            = bmh->bmh_Top;
  1042.     bmh2->bmh_Width            = dstBitMapWidth;
  1043.     bmh2->bmh_Height        = dstBitMapHeight;
  1044.     bmh2->bmh_Depth            = bmh->bmh_Depth;
  1045.     bmh2->bmh_PageWidth        = max(bmh2->bmh_Width,bmh->bmh_PageWidth);
  1046.     bmh2->bmh_PageHeight    = max(bmh2->bmh_Height,bmh->bmh_PageHeight);
  1047.     bmh2->bmh_Transparent    = 0;
  1048.     bmh2->bmh_Masking        = mskHasTransparentColor;
  1049.     bmh2->bmh_XAspect        = 1;
  1050.     bmh2->bmh_YAspect        = 1;
  1051.  
  1052.     memcpy(cregs2,cregs,numColours * 3 * sizeof(ULONG));
  1053.     memcpy(cmap2,cmap,numColours * sizeof(*cmap));
  1054.  
  1055.     if(to != NULL)
  1056.     {
  1057.         strcpy(nameBuffer,to);
  1058.         AddPart(nameBuffer,FilePart(fileName),MatchLen);
  1059.         strcat(nameBuffer,PadSuffix);
  1060.     }
  1061.     else
  1062.     {
  1063.         strcpy(nameBuffer,fileName);
  1064.         strcat(nameBuffer,PadSuffix);
  1065.     }
  1066.  
  1067.     Printf("writing file \"%s\"... ",nameBuffer);
  1068.     Flush(Output());
  1069.  
  1070.     file = Open(nameBuffer,MODE_NEWFILE);
  1071.     if(file == ZERO)
  1072.     {
  1073.         error = IoErr();
  1074.         goto out;
  1075.     }
  1076.  
  1077.     if(CANNOT DoMethod(out,DTM_WRITE,NULL,file,DTWM_IFF,NULL))
  1078.     {
  1079.         error = IoErr();
  1080.         Close(file);
  1081.         file = ZERO;
  1082.         DeleteFile(nameBuffer);
  1083.         goto out;
  1084.     }
  1085.  
  1086.  out:
  1087.  
  1088.     if(file != ZERO)
  1089.         Close(file);
  1090.  
  1091.     FreeBitMap(dstBitMap);
  1092.  
  1093.     DisposeDTObject(obj);
  1094.     DisposeDTObject(out);
  1095.  
  1096.     if(error != -1)
  1097.     {
  1098.         if(error == OK)
  1099.         {
  1100.             Printf("Ok\n");
  1101.         }
  1102.         else
  1103.         {
  1104.             if(error < 2000)
  1105.             {
  1106.                 UBYTE buffer[100];
  1107.  
  1108.                 Fault(error,NULL,buffer,sizeof(buffer));
  1109.                 Printf("%s\n",buffer);
  1110.             }
  1111.             else
  1112.             {
  1113.                 Printf("%s\n",GetDTString(error));
  1114.             }
  1115.         }
  1116.     }
  1117. }
  1118.  
  1119. /****************************************************************************/
  1120.  
  1121. int
  1122. main(int argc,char ** argv)
  1123. {
  1124.     struct
  1125.     {
  1126.         KEY *    Files;
  1127.         KEY        To;
  1128.         SWITCH    Dither;
  1129.         NUMBER    Darken;
  1130.         SWITCH    Pad;
  1131.     } args;
  1132.     STRPTR argsTemplate =
  1133.         "FILES/M,"
  1134.         "TO/K,"
  1135.         "DITHER/S,"
  1136.         "DARKEN/K/N,"
  1137.         "PAD/S";
  1138.  
  1139.     struct AnchorPath * ap = NULL;
  1140.     BOOL matched = FALSE;
  1141.     struct RDArgs * rda = NULL;
  1142.     STRPTR * files;
  1143.     STRPTR file;
  1144.     int result = RETURN_FAIL;
  1145.     LONG error = OK;
  1146.     STRPTR altBuffer = NULL;
  1147.     STRPTR name = NULL;
  1148.     BOOL isFile;
  1149.     LONG darken;
  1150.     ULONG a,b;
  1151.  
  1152.     if(SysBase->lib_Version < 39)
  1153.     {
  1154.         printf("AmigaOS 3.0 required.\n");
  1155.         goto out;
  1156.     }
  1157.  
  1158.     memset(&args,0,sizeof(args));
  1159.  
  1160.     ap = AllocVec(sizeof(*ap) + MatchLen,MEMF_ANY|MEMF_PUBLIC);
  1161.     if(ap == NULL)
  1162.     {
  1163.         error = ERROR_NO_FREE_STORE;
  1164.         goto out;
  1165.     }
  1166.  
  1167.     memset(ap,0,sizeof(*ap));
  1168.     ap->ap_Strlen        = MatchLen;
  1169.     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  1170.  
  1171.     altBuffer = AllocVec(MatchLen + 40,MEMF_ANY|MEMF_PUBLIC);
  1172.     if(altBuffer == NULL)
  1173.     {
  1174.         error = ERROR_NO_FREE_STORE;
  1175.         goto out;
  1176.     }
  1177.  
  1178.     name = AllocVec(MatchLen + 1,MEMF_ANY|MEMF_PUBLIC);
  1179.     if(name == NULL)
  1180.     {
  1181.         error = ERROR_NO_FREE_STORE;
  1182.         goto out;
  1183.     }
  1184.  
  1185.     rda = ReadArgs(argsTemplate,(LONG *)&args,NULL);
  1186.     if(rda == NULL)
  1187.     {
  1188.         error = IoErr();
  1189.         goto out;
  1190.     }
  1191.  
  1192.     files = args.Files;
  1193.     if(files == NULL)
  1194.     {
  1195.         error = ERROR_REQUIRED_ARG_MISSING;
  1196.         goto out;
  1197.     }
  1198.  
  1199.     CurrentTime(&a,&b);
  1200.  
  1201.     SetRandomSeed(a+b);
  1202.  
  1203.     if(args.Darken != NULL)
  1204.         darken = (*args.Darken);
  1205.     else
  1206.         darken = 40;
  1207.  
  1208.     while((file = (*files++)) != NULL)
  1209.     {
  1210.         if(matched)
  1211.         {
  1212.             MatchEnd(ap);
  1213.  
  1214.             memset(ap,0,sizeof(*ap));
  1215.             ap->ap_Strlen        = MatchLen;
  1216.             ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  1217.         }
  1218.  
  1219.         error = MatchFirst(file,ap);
  1220.         matched = TRUE;
  1221.  
  1222.         if(FIB_IS_DRAWER(&ap->ap_Info))
  1223.             ap->ap_Flags |= APF_DODIR;
  1224.  
  1225.         while(error == OK)
  1226.         {
  1227.             isFile = FIB_IS_FILE(&ap->ap_Info);
  1228.             if(isFile)
  1229.                 strcpy(name,ap->ap_Buf);
  1230.  
  1231.             error = MatchNext(ap);
  1232.  
  1233.             if(isFile)
  1234.             {
  1235.                 int len = strlen(name);
  1236.  
  1237.                 if(args.Pad)
  1238.                 {
  1239.                     if(len > strlen(PadSuffix) && Stricmp(&name[len - strlen(PadSuffix)],(STRPTR)PadSuffix) == SAME)
  1240.                         continue;
  1241.  
  1242.                     AddPadding(name,altBuffer,args.To);
  1243.                 }
  1244.                 else
  1245.                 {
  1246.                     if(len > strlen(GlowSuffix) && Stricmp(&name[len - strlen(GlowSuffix)],(STRPTR)GlowSuffix) == SAME)
  1247.                         continue;
  1248.  
  1249.                     AddGlow(name,altBuffer,args.To,args.Dither,darken);
  1250.                 }
  1251.             }
  1252.         }
  1253.  
  1254.         if(error == ERROR_NO_MORE_ENTRIES)
  1255.             error = OK;
  1256.  
  1257.         if(error != OK && error != ERROR_NO_MORE_ENTRIES)
  1258.             break;
  1259.     }
  1260.  
  1261.     if(error == OK || error == ERROR_BREAK)
  1262.         result = RETURN_OK;
  1263.  
  1264.  out:
  1265.  
  1266.     if(error != OK)
  1267.         PrintFault(error,FilePart(argv[0]));
  1268.  
  1269.     if(altBuffer != NULL)
  1270.         FreeVec(altBuffer);
  1271.  
  1272.     if(name != NULL)
  1273.         FreeVec(name);
  1274.  
  1275.     if(ap != NULL)
  1276.     {
  1277.         if(matched)
  1278.             MatchEnd(ap);
  1279.  
  1280.         FreeVec(ap);
  1281.     }
  1282.  
  1283.     if(rda != NULL)
  1284.         FreeArgs(rda);
  1285.  
  1286.     return(result);
  1287. }
  1288.