home *** CD-ROM | disk | FTP | other *** search
/ Global Amiga Experience / globalamigaexperience.iso / compressed / graphic / arteffectdemodisk1.dms / arteffectdemodisk1.adf / 3rd_party / neumann.lha / spr.c < prev   
C/C++ Source or Header  |  1995-03-23  |  11KB  |  446 lines

  1.  
  2. /*
  3.     Displace_Pixel plugin for ArtEffect
  4.  
  5.     Written and Copyright (c) March 1995 by Frank Neumann
  6.  
  7.     This program and the included source code are freely distributable.
  8.     It is heavily based on the source of the "Mosaic" plugin by Alexander
  9.     Pratsch. The idea for the displacement effect itself comes from my
  10.     'ppmspread' program, as distributed with the netpbm package.
  11.  
  12.     ToDO:
  13.     Schneller !
  14.     Problem mit Masken...?
  15.  
  16.     Bugs:
  17.     It's too slow... (ADPro's DisplacePixel operator is three times as fast)
  18.  
  19. */
  20.  
  21. /*** INCLUDES ***/
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <strings.h>
  25. #include <time.h>
  26.  
  27. #include <exec/types.h>
  28. #include <exec/memory.h>
  29. #include <dos/dos.h>
  30. #include <dos/rdargs.h>
  31. #include <egs/egsutil.h>
  32. #include <egs/ownall.h>
  33.  
  34. #include <proto/exec.h>
  35. #include <proto/dos.h>
  36. #include <egs/proto/egsutil.h>
  37. #include "ArtEffect:Developer/picotalk.h"
  38.  
  39. #define ET_CreateWindowTags ET_CreateWindow
  40. #define ET_CreateVertiBoxTags ET_CreateVertiBox
  41. #define ET_CreateHorizBoxTags ET_CreateHorizBox
  42. #define ET_CreateValueGadTags ET_CreateValueGad
  43.  
  44. /*** GLOBAL VARIABLES ***/
  45. const char *ver = "$VER: Displace_Pixel 0.3 (23.03.95)";
  46.  
  47. struct Library *EGBBase = NULL;
  48. struct Library *EGSUtilBase = NULL;
  49. struct Library *EGSIntuiBase = NULL;
  50.  
  51. struct EI_Window *window = NULL, *win2 = NULL;
  52. struct MsgPort *myport = NULL;
  53. struct PicoMsg *msg = NULL;
  54. EB_GadContext con = NULL, con2 = NULL;
  55. ULONG appid;
  56. struct ET_ProgressBox myprogress;
  57.  
  58. /*** DEFINES ETC ***/
  59. enum gadgets { GAD_SIZE=100, GAD_START };
  60.  
  61. /*** PROTOTYPES ***/
  62. void          main( int, char *[] );
  63. void          crash( char * string );
  64. BOOL          SendMsg( struct Message *msg );
  65. int           ExecuteOp( struct PicoMsg *msg, int amount );
  66.  
  67. /**** START OF FUNCTIONS ****/
  68.  
  69. BOOL SendMsg(struct Message *msg)
  70. {
  71.     struct MsgPort *port;
  72.     BOOL success;
  73.  
  74.     msg->mn_Node.ln_Type = NT_MESSAGE;
  75.     msg->mn_ReplyPort = myport;
  76.     msg->mn_Length = sizeof(struct PicoMsg);
  77.  
  78.     Forbid();
  79.     if (port = FindPort("PicoTalk"))
  80.     {
  81.         PutMsg(port, msg);
  82.         WaitPort(myport);
  83.         msg = GetMsg(myport);
  84.         success = TRUE;
  85.     }
  86.     else
  87.         success = FALSE;
  88.  
  89.     Permit();
  90.     return success;
  91. }
  92.  
  93. int ExecuteOp(struct PicoMsg *msg, int amount)
  94. {
  95.     struct E_EBitMap *bitmap;
  96.     ULONG winid;
  97.     UBYTE *srcdata, *destdata, *d2, *srcimg;
  98.     int i, j, xdis, ydis, xnew, ynew;
  99.     int cols, rows;
  100.     unsigned long oldval;
  101.     time_t timenow;
  102.     int ret;
  103.  
  104.     msg->command = PTALK_OBTAIN_CURRENT;
  105.     msg->arg.winid = 0;
  106.     msg->res.alloc.bitmap = NULL;
  107.  
  108.     ret = SendMsg((struct Message *)msg);
  109.     if (!ret)
  110.         crash("execute_op: unable to send msg to ArtEffect");
  111.  
  112.     winid = msg->res.alloc.winid;
  113.     bitmap = msg->res.alloc.bitmap;
  114.  
  115.     if (bitmap)
  116.     {
  117.         cols = bitmap->Width;
  118.         rows = bitmap->Height;
  119.  
  120.         /* if we have an undo buffer, use that one as source. */
  121.         if (msg->res.alloc.source)
  122.         {
  123.             srcdata = msg->res.alloc.source->Typekey.PixelMap.Planes.Dest;
  124.             srcimg = srcdata;
  125.             destdata = msg->res.alloc.bitmap->Typekey.PixelMap.Planes.Dest;
  126.         }
  127.         else
  128.         {
  129.             /* if no undo buffer could be allocated, we have to use our own second buffer */
  130.             srcdata = msg->res.alloc.bitmap->Typekey.PixelMap.Planes.Dest;
  131.             srcimg = srcdata;
  132.             destdata = AllocMem(cols * rows * 4, MEMF_CLEAR);
  133.         }
  134.         if (destdata)
  135.         {
  136.             win2 = EB_OpenGadWindow(con2);
  137.             if (!win2)
  138.                 crash("unable to open second GadWindow");
  139.  
  140.             ET_ModifyProgressBox(win2, &myprogress, 0);
  141.  
  142.             timenow = time(NULL);
  143.             srand(timenow);
  144.  
  145.             for (i = 0; i < rows; i++)
  146.             {
  147.                 for (j = 0; j < cols; j++)
  148.                 {
  149.                     xdis = (rand() % (amount+1)) - ((amount+1) / 2);
  150.                     ydis = (rand() % (amount+1)) - ((amount+1) / 2);
  151.  
  152.                     xnew = j + xdis;
  153.                     ynew = i + ydis;
  154.  
  155.                     /* only set the displaced pixel if it's within the bounds of the image */
  156.                     if (xnew >= 0 && xnew < cols && ynew >= 0 && ynew < rows)
  157.                     {
  158.                         /* displacing a pixel is accomplished by swapping it with another */
  159.                         /* pixel in its vicinity - so, first store other pixel's RGB      */
  160.  
  161.                         d2 = srcdata + (xnew * 4) + (ynew * bitmap->BytesPerRow);
  162.                         oldval = *(unsigned long *)d2;
  163.  
  164.                         /* set second pixel to new value */
  165.                         d2 = destdata + (xnew * 4) + (ynew * bitmap->BytesPerRow);
  166.                         *(unsigned long *)d2 = *(unsigned long *)srcimg;
  167.  
  168.                         /* now, set first pixel to (old) value of second */
  169.                         d2 = destdata + (j * 4) + (i * bitmap->BytesPerRow);
  170.                         *(unsigned long *)d2 = oldval;
  171.  
  172.                         // skip alpha channel: alpha channel is also used for your calculations
  173.                         // you may also change the alpha channel, and afterwards your result will
  174.                         // be mixed accordingly.
  175.                         // you define the visibility like this: 255: your value, 0: old value
  176.                     }
  177.                     else
  178.                     {
  179.                         /* displaced pixel is out of bounds; leave the old pixel there */
  180.                         d2 = destdata + (j * 4) + (i * bitmap->BytesPerRow);
  181.                         *(unsigned long *)d2 = *(unsigned long *)srcimg;
  182.                     }
  183.                     srcimg += 4;
  184.                 }
  185.  
  186.                 ET_ModifyProgressBox(win2, &myprogress, (i * 100) / rows);
  187.             }
  188.  
  189.             EB_CloseGadWindow(con2);
  190.  
  191.             /* copy entire data from dest buffer into image buffer */
  192.             /* (srcdata is the DESTINATION !) */
  193.             /* this need not be done if we painted from Undo buffer into source buffer */
  194.             if (!msg->res.alloc.source)
  195.                 memmove(srcdata, destdata, cols * rows * 4);
  196.  
  197.             /* update window buffer */
  198.             // always has to be used (does the automatic alpha channel support)
  199.             msg->command = PTALK_UPDATE_WINDOW;
  200.             msg->arg.update.winid = winid;
  201.             msg->arg.update.left = 0;
  202.             msg->arg.update.top = 0;
  203.             msg->arg.update.width = cols;
  204.             msg->arg.update.height = rows;
  205.             SendMsg((struct Message *)msg);
  206.  
  207.             /* and free dest buffer if we allocated one */
  208.             if (!msg->res.alloc.source)
  209.                 FreeMem(destdata, cols * rows * 4);
  210.         }
  211.         if (bitmap)
  212.         {
  213.             msg->command = PTALK_RELEASE_WINDOW;
  214.             msg->arg.winid = winid;
  215.             SendMsg((struct Message *)msg);
  216.             return 0;
  217.         }
  218.         else
  219.             return - 30;
  220.     }
  221.     else
  222.         return -30;
  223. }
  224.  
  225. /*** main function ***/
  226. void main(int argc, char *argv[])
  227. {
  228.     struct EI_Screen *screen;
  229.     ULONG sigbits;
  230.     BOOL loop = TRUE;
  231.     int ret, sizeval;
  232.  
  233.     EGSIntuiBase = OpenLibrary("egsintui.library", 7);
  234.     if (!EGSIntuiBase)
  235.         crash("need egsintui.library v7");
  236.  
  237.     EGBBase = OpenLibrary("egsgadbox.library", 7);
  238.     if (!EGBBase)
  239.         crash("need egsgadbox.library v7");
  240.  
  241.     EGSUtilBase = OpenLibrary("egsutil.library", 7);
  242.     if (!EGSUtilBase)
  243.         crash("need egsutil.library v7");
  244.  
  245.     myport = CreateMsgPort();
  246.     if (!myport)
  247.         crash("unable to create MsgPort");
  248.  
  249.     msg = AllocVec(sizeof(struct PicoMsg), MEMF_PUBLIC | MEMF_CLEAR);
  250.     if (!msg)
  251.         crash("unable to allocate msg vector");
  252.  
  253.     msg->command = PTALK_NOTIFY;
  254.     msg->arg.notify.ApplicationPort = myport;
  255.     msg->arg.notify.ApplicationName = "DISPLACE_PIXEL";
  256.  
  257.     ret = SendMsg((struct Message *)msg);
  258.     if (ret == FALSE)
  259.         crash("unable to send messages to ArtEffect port");
  260.  
  261.     appid = msg->res.notify.ApplicationId;
  262.     screen = msg->res.notify.screen;
  263.  
  264.     con = EB_CreateGadContext(NULL, NULL, -1, -1);
  265.     if (!con)
  266.         crash("unable to create gadget context");
  267.  
  268.     ret = ET_CreateWindowTags(con, NULL,
  269.         ET_CreateVertiBoxTags(con,
  270.             ET_CreateHorizBoxTags(con,
  271.                 EB_CreateText(con, "Displacement area"),
  272.                 EB_NewMinWidth(ET_CreateValueGadTags(con, 1, 256, GAD_SIZE, TAG_DONE), 128),
  273.                 ET_DONE),
  274.             EB_CreateVertiFill(con, EB_FILL_ALL, -1),
  275.             EB_CreateTextAction(con, "_Modify Picture", GAD_START, EB_FILL_ALL),
  276.             ET_DONE),
  277.         ETW_SysGadgets, EI_WINDOWCLOSE | EI_WINDOWFRONT | EI_WINDOWDRAG,
  278.         ETW_Title, "Displace_Pixel",
  279.         ETW_Flags, EI_WINDOWACTIVE | EI_SIZEBRIGHT | EI_SMART_REFRESH | EI_WINDOWCENTER,
  280.         ETW_IDCMP, EI_iGADGETDOWN | EI_iCLOSEWINDOW,
  281.         ETW_AutoResize, TRUE,
  282.         ETW_PubScreen, screen,
  283.         TAG_DONE);
  284.  
  285.     if (ret)
  286.         crash("unable to create GUI tree");
  287.  
  288.     con2 = EB_CreateGadContext(NULL, NULL, -1, -1);
  289.     if (!con2)
  290.         crash("unable to create second gadget context");
  291.  
  292.     ret = ET_CreateWindowTags(con2, NULL,
  293.         ET_CreateVertiBoxTags(con2,
  294.             ET_CreateProgressBox(con2, &myprogress, 200, 200, 30, 30),
  295.             ET_DONE),
  296.         ETW_SysGadgets, EI_WINDOWFRONT | EI_WINDOWDRAG,
  297.         ETW_Title, "DisplacePixel completion",
  298.         ETW_Flags, EI_WINDOWACTIVE | EI_SIZEBRIGHT | EI_SMART_REFRESH | EI_WINDOWCENTER | EI_GIMMEZEROZERO,
  299.         ETW_AutoResize, TRUE,
  300.         ETW_PubScreen, screen,
  301.         TAG_DONE);
  302.  
  303.     if (ret)
  304.         crash("unable to create GUI tree");
  305.  
  306.     window = EB_OpenGadWindow(con);
  307.     if (!window)
  308.         crash("unable to open GadWindow");
  309.  
  310.     ET_ModifyValueGad(window, (struct ET_ValueGad *)EB_GCFindGadget(con, GAD_SIZE), 4);
  311.     sizeval = 4;
  312.  
  313.     sigbits = (1 << window->UserPort->mp_SigBit) | (1 << myport->mp_SigBit);
  314.     do
  315.     {
  316.         union
  317.         {
  318.             struct Message *msg;
  319.             struct EI_EIntuiMsg *intui;
  320.         } execmsg;
  321.  
  322.         Wait(sigbits);
  323.  
  324.         {
  325.             struct PicoMsg *msg2;
  326.             while (msg2 = (struct PicoMsg *)GetMsg(myport))
  327.             {
  328.                 switch (msg2->command)
  329.                 {
  330.                     case PTALK_APPLICATION_QUIT:
  331.                         loop = FALSE;
  332.                         break;
  333.  
  334.                     case PTALK_APPLICATION_CMD:
  335.                     {
  336.                         struct RDArgs *rdargs;
  337.                         long *dummy,size;
  338.  
  339.                         dummy = &size;
  340.  
  341.                         // parse rexx command
  342.                         if (rdargs = AllocDosObject(DOS_RDARGS, NULL))
  343.                         {
  344.                             rdargs->RDA_Source.CS_Buffer = msg2->arg.cmd.CommandString;
  345.                             rdargs->RDA_Source.CS_Length = strlen(msg2->arg.cmd.CommandString);
  346.                             rdargs->RDA_Source.CS_CurChr = 0;
  347.                             rdargs->RDA_DAList = NULL;
  348.                             rdargs->RDA_Buffer = NULL;
  349.                             rdargs->RDA_Flags = RDAF_NOPROMPT;
  350.  
  351.                             if (ReadArgs("SIZE/N/A", &dummy, rdargs))
  352.                             {
  353.                                 if ( dummy && (size >= 1) && (size <= 256) )
  354.                                     msg2->res.cmd.error = ExecuteOp(msg, size);
  355.                                 else
  356.                                     msg2->res.cmd.error = -30;
  357.                             }
  358.                             else
  359.                                 msg2->res.cmd.error = -20;
  360.  
  361.                             FreeArgs( rdargs );
  362.                             FreeDosObject(DOS_RDARGS, rdargs);
  363.                         }
  364.                     }
  365.                     break;
  366.                 }
  367.                 ReplyMsg(&msg2->msg);
  368.             }
  369.         }
  370.         while (execmsg.msg = GetMsg(window->UserPort))
  371.         {
  372.             switch (execmsg.intui->Class)
  373.             {
  374.                 case EI_iGADGETDOWN:
  375.                     switch (((struct EI_Gadget *)execmsg.intui->IAddress)->GadgetID)
  376.                     {
  377.                         case GAD_SIZE:
  378.                             sizeval = ((struct ET_ValueGad *)execmsg.intui->IAddress)->Value;
  379.                             break;
  380.                         case GAD_START:
  381.                             EI_SetPointer(window, EI_GetPrefPointer(EIM_WORKING_MOUSE));
  382.                             ExecuteOp(msg, sizeval);
  383.                             EI_SetPointer(window, EI_GetPrefPointer(EIM_STANDARD_MOUSE));
  384.                             break;
  385.                         default:
  386.                             fprintf(stderr, "You should never see this - call 1-800-SHOE.\n");
  387.                             break;
  388.                     }
  389.                     break;
  390.                 case EI_iCLOSEWINDOW:
  391.                     loop = FALSE;
  392.                     break;
  393.             }
  394.             ReplyMsg(execmsg.msg);
  395.         }
  396.     }
  397.     while (loop);
  398.  
  399.     crash(NULL);
  400. }
  401.  
  402.  
  403. /**************************************************/
  404. /* crash function - frees all allocated resources */
  405. /**************************************************/
  406. void crash(char * string)
  407. {
  408.     if (con2)
  409.         EB_DeleteGadContext(con2);
  410.  
  411.     if (con)
  412.     {
  413.         EB_CloseGadWindow(con);
  414.         EB_DeleteGadContext(con);
  415.     }
  416.  
  417.     if (msg)
  418.     {
  419.         msg->command = PTALK_LEAVE;
  420.         msg->arg.leave.ApplicationId = appid;
  421.         /* we do not care about this function's return value.. */
  422.         SendMsg((struct Message *)msg);
  423.         FreeVec(msg);
  424.     }
  425.  
  426.     if (myport)
  427.         DeleteMsgPort(myport);
  428.  
  429.     if (EGSUtilBase != NULL)
  430.         CloseLibrary(EGSUtilBase);
  431.  
  432.     if (EGBBase != NULL)
  433.         CloseLibrary(EGBBase);
  434.  
  435.     if (EGSIntuiBase != NULL)
  436.         CloseLibrary(EGSIntuiBase);
  437.  
  438.     if (NULL == string)
  439.         exit (0);
  440.     else
  441.     {
  442.         printf ("%s.\n", string);
  443.         exit (10);
  444.     }
  445. }
  446.