home *** CD-ROM | disk | FTP | other *** search
-
- /*
- Displace_Pixel plugin for ArtEffect
-
- Written and Copyright (c) March 1995 by Frank Neumann
-
- This program and the included source code are freely distributable.
- It is heavily based on the source of the "Mosaic" plugin by Alexander
- Pratsch. The idea for the displacement effect itself comes from my
- 'ppmspread' program, as distributed with the netpbm package.
-
- ToDO:
- Schneller !
- Problem mit Masken...?
-
- Bugs:
- It's too slow... (ADPro's DisplacePixel operator is three times as fast)
-
- */
-
- /*** INCLUDES ***/
- #include <stdlib.h>
- #include <stdio.h>
- #include <strings.h>
- #include <time.h>
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
- #include <dos/rdargs.h>
- #include <egs/egsutil.h>
- #include <egs/ownall.h>
-
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <egs/proto/egsutil.h>
- #include "ArtEffect:Developer/picotalk.h"
-
- #define ET_CreateWindowTags ET_CreateWindow
- #define ET_CreateVertiBoxTags ET_CreateVertiBox
- #define ET_CreateHorizBoxTags ET_CreateHorizBox
- #define ET_CreateValueGadTags ET_CreateValueGad
-
- /*** GLOBAL VARIABLES ***/
- const char *ver = "$VER: Displace_Pixel 0.3 (23.03.95)";
-
- struct Library *EGBBase = NULL;
- struct Library *EGSUtilBase = NULL;
- struct Library *EGSIntuiBase = NULL;
-
- struct EI_Window *window = NULL, *win2 = NULL;
- struct MsgPort *myport = NULL;
- struct PicoMsg *msg = NULL;
- EB_GadContext con = NULL, con2 = NULL;
- ULONG appid;
- struct ET_ProgressBox myprogress;
-
- /*** DEFINES ETC ***/
- enum gadgets { GAD_SIZE=100, GAD_START };
-
- /*** PROTOTYPES ***/
- void main( int, char *[] );
- void crash( char * string );
- BOOL SendMsg( struct Message *msg );
- int ExecuteOp( struct PicoMsg *msg, int amount );
-
- /**** START OF FUNCTIONS ****/
-
- BOOL SendMsg(struct Message *msg)
- {
- struct MsgPort *port;
- BOOL success;
-
- msg->mn_Node.ln_Type = NT_MESSAGE;
- msg->mn_ReplyPort = myport;
- msg->mn_Length = sizeof(struct PicoMsg);
-
- Forbid();
- if (port = FindPort("PicoTalk"))
- {
- PutMsg(port, msg);
- WaitPort(myport);
- msg = GetMsg(myport);
- success = TRUE;
- }
- else
- success = FALSE;
-
- Permit();
- return success;
- }
-
- int ExecuteOp(struct PicoMsg *msg, int amount)
- {
- struct E_EBitMap *bitmap;
- ULONG winid;
- UBYTE *srcdata, *destdata, *d2, *srcimg;
- int i, j, xdis, ydis, xnew, ynew;
- int cols, rows;
- unsigned long oldval;
- time_t timenow;
- int ret;
-
- msg->command = PTALK_OBTAIN_CURRENT;
- msg->arg.winid = 0;
- msg->res.alloc.bitmap = NULL;
-
- ret = SendMsg((struct Message *)msg);
- if (!ret)
- crash("execute_op: unable to send msg to ArtEffect");
-
- winid = msg->res.alloc.winid;
- bitmap = msg->res.alloc.bitmap;
-
- if (bitmap)
- {
- cols = bitmap->Width;
- rows = bitmap->Height;
-
- /* if we have an undo buffer, use that one as source. */
- if (msg->res.alloc.source)
- {
- srcdata = msg->res.alloc.source->Typekey.PixelMap.Planes.Dest;
- srcimg = srcdata;
- destdata = msg->res.alloc.bitmap->Typekey.PixelMap.Planes.Dest;
- }
- else
- {
- /* if no undo buffer could be allocated, we have to use our own second buffer */
- srcdata = msg->res.alloc.bitmap->Typekey.PixelMap.Planes.Dest;
- srcimg = srcdata;
- destdata = AllocMem(cols * rows * 4, MEMF_CLEAR);
- }
- if (destdata)
- {
- win2 = EB_OpenGadWindow(con2);
- if (!win2)
- crash("unable to open second GadWindow");
-
- ET_ModifyProgressBox(win2, &myprogress, 0);
-
- timenow = time(NULL);
- srand(timenow);
-
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- xdis = (rand() % (amount+1)) - ((amount+1) / 2);
- ydis = (rand() % (amount+1)) - ((amount+1) / 2);
-
- xnew = j + xdis;
- ynew = i + ydis;
-
- /* only set the displaced pixel if it's within the bounds of the image */
- if (xnew >= 0 && xnew < cols && ynew >= 0 && ynew < rows)
- {
- /* displacing a pixel is accomplished by swapping it with another */
- /* pixel in its vicinity - so, first store other pixel's RGB */
-
- d2 = srcdata + (xnew * 4) + (ynew * bitmap->BytesPerRow);
- oldval = *(unsigned long *)d2;
-
- /* set second pixel to new value */
- d2 = destdata + (xnew * 4) + (ynew * bitmap->BytesPerRow);
- *(unsigned long *)d2 = *(unsigned long *)srcimg;
-
- /* now, set first pixel to (old) value of second */
- d2 = destdata + (j * 4) + (i * bitmap->BytesPerRow);
- *(unsigned long *)d2 = oldval;
-
- // skip alpha channel: alpha channel is also used for your calculations
- // you may also change the alpha channel, and afterwards your result will
- // be mixed accordingly.
- // you define the visibility like this: 255: your value, 0: old value
- }
- else
- {
- /* displaced pixel is out of bounds; leave the old pixel there */
- d2 = destdata + (j * 4) + (i * bitmap->BytesPerRow);
- *(unsigned long *)d2 = *(unsigned long *)srcimg;
- }
- srcimg += 4;
- }
-
- ET_ModifyProgressBox(win2, &myprogress, (i * 100) / rows);
- }
-
- EB_CloseGadWindow(con2);
-
- /* copy entire data from dest buffer into image buffer */
- /* (srcdata is the DESTINATION !) */
- /* this need not be done if we painted from Undo buffer into source buffer */
- if (!msg->res.alloc.source)
- memmove(srcdata, destdata, cols * rows * 4);
-
- /* update window buffer */
- // always has to be used (does the automatic alpha channel support)
- msg->command = PTALK_UPDATE_WINDOW;
- msg->arg.update.winid = winid;
- msg->arg.update.left = 0;
- msg->arg.update.top = 0;
- msg->arg.update.width = cols;
- msg->arg.update.height = rows;
- SendMsg((struct Message *)msg);
-
- /* and free dest buffer if we allocated one */
- if (!msg->res.alloc.source)
- FreeMem(destdata, cols * rows * 4);
- }
- if (bitmap)
- {
- msg->command = PTALK_RELEASE_WINDOW;
- msg->arg.winid = winid;
- SendMsg((struct Message *)msg);
- return 0;
- }
- else
- return - 30;
- }
- else
- return -30;
- }
-
- /*** main function ***/
- void main(int argc, char *argv[])
- {
- struct EI_Screen *screen;
- ULONG sigbits;
- BOOL loop = TRUE;
- int ret, sizeval;
-
- EGSIntuiBase = OpenLibrary("egsintui.library", 7);
- if (!EGSIntuiBase)
- crash("need egsintui.library v7");
-
- EGBBase = OpenLibrary("egsgadbox.library", 7);
- if (!EGBBase)
- crash("need egsgadbox.library v7");
-
- EGSUtilBase = OpenLibrary("egsutil.library", 7);
- if (!EGSUtilBase)
- crash("need egsutil.library v7");
-
- myport = CreateMsgPort();
- if (!myport)
- crash("unable to create MsgPort");
-
- msg = AllocVec(sizeof(struct PicoMsg), MEMF_PUBLIC | MEMF_CLEAR);
- if (!msg)
- crash("unable to allocate msg vector");
-
- msg->command = PTALK_NOTIFY;
- msg->arg.notify.ApplicationPort = myport;
- msg->arg.notify.ApplicationName = "DISPLACE_PIXEL";
-
- ret = SendMsg((struct Message *)msg);
- if (ret == FALSE)
- crash("unable to send messages to ArtEffect port");
-
- appid = msg->res.notify.ApplicationId;
- screen = msg->res.notify.screen;
-
- con = EB_CreateGadContext(NULL, NULL, -1, -1);
- if (!con)
- crash("unable to create gadget context");
-
- ret = ET_CreateWindowTags(con, NULL,
- ET_CreateVertiBoxTags(con,
- ET_CreateHorizBoxTags(con,
- EB_CreateText(con, "Displacement area"),
- EB_NewMinWidth(ET_CreateValueGadTags(con, 1, 256, GAD_SIZE, TAG_DONE), 128),
- ET_DONE),
- EB_CreateVertiFill(con, EB_FILL_ALL, -1),
- EB_CreateTextAction(con, "_Modify Picture", GAD_START, EB_FILL_ALL),
- ET_DONE),
- ETW_SysGadgets, EI_WINDOWCLOSE | EI_WINDOWFRONT | EI_WINDOWDRAG,
- ETW_Title, "Displace_Pixel",
- ETW_Flags, EI_WINDOWACTIVE | EI_SIZEBRIGHT | EI_SMART_REFRESH | EI_WINDOWCENTER,
- ETW_IDCMP, EI_iGADGETDOWN | EI_iCLOSEWINDOW,
- ETW_AutoResize, TRUE,
- ETW_PubScreen, screen,
- TAG_DONE);
-
- if (ret)
- crash("unable to create GUI tree");
-
- con2 = EB_CreateGadContext(NULL, NULL, -1, -1);
- if (!con2)
- crash("unable to create second gadget context");
-
- ret = ET_CreateWindowTags(con2, NULL,
- ET_CreateVertiBoxTags(con2,
- ET_CreateProgressBox(con2, &myprogress, 200, 200, 30, 30),
- ET_DONE),
- ETW_SysGadgets, EI_WINDOWFRONT | EI_WINDOWDRAG,
- ETW_Title, "DisplacePixel completion",
- ETW_Flags, EI_WINDOWACTIVE | EI_SIZEBRIGHT | EI_SMART_REFRESH | EI_WINDOWCENTER | EI_GIMMEZEROZERO,
- ETW_AutoResize, TRUE,
- ETW_PubScreen, screen,
- TAG_DONE);
-
- if (ret)
- crash("unable to create GUI tree");
-
- window = EB_OpenGadWindow(con);
- if (!window)
- crash("unable to open GadWindow");
-
- ET_ModifyValueGad(window, (struct ET_ValueGad *)EB_GCFindGadget(con, GAD_SIZE), 4);
- sizeval = 4;
-
- sigbits = (1 << window->UserPort->mp_SigBit) | (1 << myport->mp_SigBit);
- do
- {
- union
- {
- struct Message *msg;
- struct EI_EIntuiMsg *intui;
- } execmsg;
-
- Wait(sigbits);
-
- {
- struct PicoMsg *msg2;
- while (msg2 = (struct PicoMsg *)GetMsg(myport))
- {
- switch (msg2->command)
- {
- case PTALK_APPLICATION_QUIT:
- loop = FALSE;
- break;
-
- case PTALK_APPLICATION_CMD:
- {
- struct RDArgs *rdargs;
- long *dummy,size;
-
- dummy = &size;
-
- // parse rexx command
- if (rdargs = AllocDosObject(DOS_RDARGS, NULL))
- {
- rdargs->RDA_Source.CS_Buffer = msg2->arg.cmd.CommandString;
- rdargs->RDA_Source.CS_Length = strlen(msg2->arg.cmd.CommandString);
- rdargs->RDA_Source.CS_CurChr = 0;
- rdargs->RDA_DAList = NULL;
- rdargs->RDA_Buffer = NULL;
- rdargs->RDA_Flags = RDAF_NOPROMPT;
-
- if (ReadArgs("SIZE/N/A", &dummy, rdargs))
- {
- if ( dummy && (size >= 1) && (size <= 256) )
- msg2->res.cmd.error = ExecuteOp(msg, size);
- else
- msg2->res.cmd.error = -30;
- }
- else
- msg2->res.cmd.error = -20;
-
- FreeArgs( rdargs );
- FreeDosObject(DOS_RDARGS, rdargs);
- }
- }
- break;
- }
- ReplyMsg(&msg2->msg);
- }
- }
- while (execmsg.msg = GetMsg(window->UserPort))
- {
- switch (execmsg.intui->Class)
- {
- case EI_iGADGETDOWN:
- switch (((struct EI_Gadget *)execmsg.intui->IAddress)->GadgetID)
- {
- case GAD_SIZE:
- sizeval = ((struct ET_ValueGad *)execmsg.intui->IAddress)->Value;
- break;
- case GAD_START:
- EI_SetPointer(window, EI_GetPrefPointer(EIM_WORKING_MOUSE));
- ExecuteOp(msg, sizeval);
- EI_SetPointer(window, EI_GetPrefPointer(EIM_STANDARD_MOUSE));
- break;
- default:
- fprintf(stderr, "You should never see this - call 1-800-SHOE.\n");
- break;
- }
- break;
- case EI_iCLOSEWINDOW:
- loop = FALSE;
- break;
- }
- ReplyMsg(execmsg.msg);
- }
- }
- while (loop);
-
- crash(NULL);
- }
-
-
- /**************************************************/
- /* crash function - frees all allocated resources */
- /**************************************************/
- void crash(char * string)
- {
- if (con2)
- EB_DeleteGadContext(con2);
-
- if (con)
- {
- EB_CloseGadWindow(con);
- EB_DeleteGadContext(con);
- }
-
- if (msg)
- {
- msg->command = PTALK_LEAVE;
- msg->arg.leave.ApplicationId = appid;
- /* we do not care about this function's return value.. */
- SendMsg((struct Message *)msg);
- FreeVec(msg);
- }
-
- if (myport)
- DeleteMsgPort(myport);
-
- if (EGSUtilBase != NULL)
- CloseLibrary(EGSUtilBase);
-
- if (EGBBase != NULL)
- CloseLibrary(EGBBase);
-
- if (EGSIntuiBase != NULL)
- CloseLibrary(EGSIntuiBase);
-
- if (NULL == string)
- exit (0);
- else
- {
- printf ("%s.\n", string);
- exit (10);
- }
- }
-