home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / GFX / Converter / DC-PGS21.DMS / in.adf / Extras / DevDocs.LHA / DeveloperDocs / help / efx.txt < prev    next >
Encoding:
Text File  |  1996-06-03  |  13.6 KB  |  435 lines

  1. Programming information for .EFX files (written 29/3/96 for Photogenics 2) 
  2. ==========================================================================
  3.  
  4. Copyright © Almathera Systems Ltd 1994-6. All Rights Reserved.
  5.  
  6. All programming examples and documentation is proprietary
  7. and may only be used to create .EFX files for use
  8. with the Photogenics program.
  9.  
  10. Any other use of this documentation and source is strictly
  11. prohibited. It may not be reproduced or copied without
  12. written authorisation from Almathera.
  13.  
  14. Permission is hereby given to allow free or commercial
  15. distribution of .EFX files for Photogenics written using
  16. this code. Almathera encourages the free distribution
  17. of .EFX files for use with Photogenics.
  18.  
  19. (ie. If you write an EFX, you can do whatever you want with
  20. it!)
  21.  
  22. .EFX files may not be distributed for use with any other
  23. Amiga software.
  24.  
  25. (ie. You can't reverse engineer our system and build your
  26. own image-processor around our files)
  27.  
  28. ---------------------------------------------------
  29. If you have any problems developing add-on files for
  30. Photogenics, then please contact:
  31.  
  32. Jolyon Ralph on (UK) 0181 687 0040 during office hours, or email to:
  33.  
  34. jralph@cix.compulink.co.uk
  35.  
  36. We'll be happy to help out where we can.
  37.  
  38. If you've come up with an excellent idea for a loader but
  39. can't program it yourself, then let us know and we might
  40. have a go ourselves, or call our BBS, someone may
  41. have already written one!
  42.  
  43. -----------------------------------------------------
  44.  
  45. What is an .EFX file? - Jolyon Ralph (29/3/96)
  46. ==============================================
  47.  
  48. EFX files are add-in files for Photogenics 2 that allow various image processing type
  49. functions to be applied to the image.
  50.  
  51. An .EFX file, just like the .GIO files, is a standard system disk-based library file. You can
  52. create .EFX files with any programming language that can create a library (assembler, C, C++, Modula II, etc.). 
  53. The examples provided were written using SAS V6.51 and Hisoft Devpac, but any C compiler
  54. and Assembler should be capable of compiling them with little or no alteration to the sourcecode.
  55.  
  56. Using libraries carries little overhead and has the major advantage
  57. that the Amiga operating system automatically handles ram cacheing
  58. of libraries and flushing libraries when ram is low without us having
  59. to worry about that.
  60.  
  61. Each library follows a standard function layout (as shown
  62. in the efx.fd file:)
  63.  
  64. * "efx.library"
  65. ##base __EfxBase
  66. ##bias 30
  67. ##public
  68. EfxInfo()()
  69. EfxPreRender(giodata)(a0)
  70. EfxRender(giodata)(a0)
  71. EfxPrefs(giodata)(a0)
  72. EfxAbout(giodata)(a0)
  73. ##end
  74.  
  75. First a description of the functions:
  76.  
  77.  
  78. EfxInfo
  79. =======
  80.  
  81. flags = EfxInfo(void)
  82.  d0.L
  83.  
  84. This is required by all .efx files. It returns flags depending on
  85. the capabilities of the effect. The flags are (defined in efx.h)
  86.  
  87. EFX_24BIT -
  88.  The effect will operate on 24-bit images (currently the only
  89.  type supported in Photogenics 2.0)
  90.  
  91. EFX_8GREY -
  92.  The effect will operate on 8-bit greyscale images
  93.  (which currently means paintlayer - but will also include standard 8-bit buffers
  94.   in future versions)
  95.  
  96. EFX_1BIT
  97.  The effect will operate on 1-bit monochrome images
  98.  (not implemented)
  99.  
  100. EFX_INDEXED
  101.  The effect will operate on 256 (or less) palette based
  102.  index colour images (not implemented)
  103.  
  104. EFX_NOOPTIONS -
  105.  No options page is available for this effect.
  106.  
  107. EFX_USESSECOND - 
  108.  Another image needs to be selected as the secondary to use 
  109.  this effect.
  110.  
  111. EFX_NEEDSUNDO -
  112.  The effect needs an undo buffer in order to operate 
  113.  correctly. This is essential to avoid 'feedback' situations. You will need
  114.  to use this if it is not possible to process a pixel at a time (for example if your
  115.  effect overwrites other pixels while processing).
  116.  
  117.  If your effect works on a pixel at a time, then you don't need this flag, and the effect can
  118.  be executed even if the undo buffer is not present.
  119.  
  120. EFX_PAINTLAYER -
  121.  The effect operates by altering the image paintlayer rather
  122.  than affecting the 
  123.  
  124. EFX_FULLSCREENONLY -
  125.  The effect cannot operate on a window. In this case, the effect processes every
  126.  pixel of the image.
  127.  
  128.  Normally, the window to be processed would be passed in
  129.  
  130.     giodata->WindX
  131.     giodata->WindY
  132.     giodata->WindWidth
  133.     giodata->WindHeight
  134.  
  135.  and only those pixels should be altered. If EFX_FULLSCREENONLY is set, the
  136. program knows that the whole picture, from 0,0 to giodata->Width-1, giodata->Height-1 
  137. is processed, regardless of the window position.
  138.  
  139. Obviously you should only use EFX_FULLSCREENONLY when it is not practical or sensible to
  140. allow an effect within a region.
  141.  
  142.  
  143. EfxPreRender
  144. ============
  145. This currently does nothing.
  146. Please return zero for future compatibility.
  147.  
  148. EfxRender
  149. =========
  150. This is the actual effect routine. It's pretty straight forward, and very similar to 
  151. programming for the GIO modules 
  152.  
  153. Here is some example code from Negative.efx
  154.  
  155. __asm ULONG EfxRender(register __a0 struct GIOData *giodata)
  156. {
  157. UBYTE r,g,b;
  158. int x,y;
  159.     
  160.     SetProgress("Inverting image...",0);
  161.  
  162.     switch(giodata->Depth)
  163.     {
  164.  
  165.         case 24:
  166.  
  167.             for(y=giodata->WindY;y<giodata->WindY+giodata->WindHeight;y++)
  168.             {
  169.                 if(!(y%64))
  170.                 {
  171.  
  172.                     /* SetProgress returns 1 if it wasn't cancelled! */
  173.  
  174.                     if(SetProgress(0,(y-giodata->WindY)*100/giodata->WindHeight)!=1) 
  175.                     {  
  176.                         giodata->Error = GIO_ABORTED;
  177.                         goto err;
  178.                     }
  179.                 }
  180.                 for(x=giodata->WindX;x<giodata->WindX+giodata->WindWidth;x++)
  181.                 {
  182.                     GetSrcPixel(giodata,x,y,&r,&g,&b);
  183.                     PutDestPixel(giodata,x,y,255-r,255-g,255-b);
  184.                 }
  185.             }
  186.         break;
  187.  
  188.         case 8:
  189.             for(y=giodata->WindY;y<giodata->WindY+giodata->WindHeight;y++)
  190.             {
  191.                 if(!(y%64))
  192.                 {
  193.                     if(SetProgress(0,(y-giodata->WindY)*100/giodata->WindHeight)!=1) 
  194.                     {
  195.                         giodata->Error = GIO_ABORTED;
  196.                         goto err;
  197.                     }
  198.                 }
  199.                 for(x=giodata->WindX;x<giodata->WindX+giodata->WindWidth;x++)
  200.                 {
  201.                     r=GetSrcPixel8(giodata,x,y);
  202.                     PutDestPixel8(giodata,x,y,255-r);
  203.                 }
  204.             }
  205.         break;
  206.     }
  207.     giodata->Error = GIO_OK;
  208. err:
  209.     return(giodata->Error);
  210. }
  211.  
  212. Note the important factors.
  213.  
  214. 1. Only the pixels within the window region are altered.
  215.  
  216. 2. Unlike GIO's, we read a pixel at a time with the GetSrcPixel() function.
  217.  
  218. Normally this reads from the undo buffer, so however much you alter the destination GetSrcPixel
  219. will return the original pixel values. If Undo is disabled within Photogenics, or there is not
  220. enough ram to run an undo buffer, then the Src and Destination buffers are one and the same, meaning
  221. you can't read the original colour of pixel (x,y) if you've just written over it. If your
  222. effect can't work with that, make sure you set the EFX_NEEDSUNDO flag.
  223.  
  224. 3. Once we have processed the values, we use PutDestPixel() to return the pixels to the
  225. destination image.
  226.  
  227. 4. With the 8-bit data, we use GetSrcPixel8 and PutDestPixel8 to get and put a byte of data at a time.
  228.  
  229.  
  230. Other calls you'll need to know about:
  231.  
  232. Reading each pixel with GetSrcPixel isn't the fastest way to access data.
  233. The Negative code above would be a lot faster if we used the following...
  234.  
  235. UBYTE *peeker,*poker;
  236.  
  237.         case 24:
  238.  
  239.             for(y=giodata->WindY;y<giodata->WindY+giodata->WindHeight;y++)
  240.             {
  241.                 if(!(y%64))
  242.                 {
  243.  
  244.                     /* SetProgress returns 1 if it wasn't cancelled! */
  245.  
  246.                     if(SetProgress(0,(y-giodata->WindY)*100/giodata->WindHeight)!=1) 
  247.                     {  
  248.                         giodata->Error = GIO_ABORTED;
  249.                         goto err;
  250.                     }
  251.                 }
  252.  
  253.                 peeker = GetSrcLine(giodata,y | PGVM_READONLY);    
  254.                 poker = GetDestLine(giodata,y | PGVM_WRITEONLY);
  255.  
  256.                 if(peeker && poker)
  257.                 {
  258.                     peeker+=giodata->WindX*3;
  259.                     poker+=giodata->WindX*3;
  260.                     for(x=0;x<(giodata->WindWidth*3);x++)
  261.                     {
  262.                         *poker++= 255-(*peeker++);
  263.                     }
  264.                 }
  265.                 if(peeker) ReleaseSrcLine(giodata,y | PGVM_READONLY);
  266.                 if(poker) ReleaseDestLine(giodata,y | PGVM_WRITEONLY);
  267.             }
  268.         break;
  269.  
  270. This, although a little less obvious, does the same. If you've looked at the GIO devdocs you'll 
  271. recognise the GetLine/ReleaseLine stuff.
  272.  
  273. GetSrcLine(giodata,y) returns the address of the line of 24-bit data y.
  274.  
  275. The y value is ORed with a flag:
  276.  
  277.     PGVM_READONLY         - I only want to read from the data you give me. 
  278.     PGVM_WRITEONLY        - I only want to write to the data you give me.
  279.  
  280. If you want to read and write to the data (can't see when you'd need that, unless you
  281. want to read from the destination to get feedback effects) then leave the flag off.
  282.  
  283. The reason for the flags is to speed up virtual memory access when using Virtual Image. With
  284. READONLY the data isn't written back to disk when you've finished with it, with WRITEONLY
  285. the data isn't read, but a blank line supplied to you.
  286.  
  287. If you ignore the flags your code should still work, but it will be slower when working with
  288. virtual image as it will do unnecessary reads and writes.
  289.  
  290. Once you've finished accessing the data you MUST use ReleaseSrcLine or ReleaseDestLine to
  291. free the data (and write it back to disk in the case of virtual images).
  292.  
  293. Note: all this is handled for you with GetSrcPixel() & PutDestPixel() and they even
  294. cache lines for you.
  295.  
  296. You can GetxxxLine multiple lines at a time, although it's not a wise idea to GetxxxLine every line
  297. in the image at the same time!!!!!
  298.  
  299. GetSrcPixelAA(giodata,x,y,&r,&g,&b):
  300.  
  301. Another function, not shown in the examples, is the GetSrcPixelAA() function. This gets an
  302. anti-aliased pixel from a virtual image 16 times larger in each dimension than your picture.
  303.  
  304. To use this, simply scale your x and y values by 16 (<<4) and call GetSrcPixelAA().
  305.  
  306. If you're calculating something like a wave or 3d perspective effect which returns a pixel
  307. position, multiplying by 16 and then using the AA routine will provide a much better image
  308. than you'd normally get. The Wave and Perspective effects use this code, and the Warper tool
  309. has been updated in Photogenics to work on the same principal.
  310.  
  311.  
  312. Image Previews:
  313.  
  314. Previous versions of Photogenics didn't allow you to do anything clever with requesters for
  315. previews. AS Photogenics can run in so many different screenmodes, and it is not legal for you
  316. to change the photogenics screen palette, this has proved dificult.
  317.  
  318. We've now circumvented the problem by adding a function to allow preview images to be written
  319. directly into your rastport.
  320.  
  321. This assumes
  322.  
  323. a) your source data is in 24-bit RGB format.
  324.  
  325. b) your rastport is in a window on the Photogenics screen :-)
  326.  
  327. The balance.efx code provided shows an example of opening a gadtools window with sliders, and
  328. a realtime updated preview.
  329.  
  330. preview = CreatePreviewImage(giodata,64,64,0); 
  331. is called to create a preview image 64 pixels by 64 pixels in size.
  332.  
  333. We then allocate a block of memory 64x64x3 bytes in size to store a copy of the data.
  334.  
  335. In the preview_balance routine we take a pixel at a time from the preview image,
  336. apply the effect (in this case the colour balance) to it, and place it in the copy of preview.
  337.  
  338. The DrawPreviewImage(giodata,rastport,data,x,y,width,height) routine then
  339. draws the preview into the rastport.
  340.  
  341. You don't need to have created the data with CreatePreviewImage in order to use DrawPreviewImage, you
  342. can allocate your own memory and send it to DrawPreviewImage, as long as you send RGB data with
  343. three bytes per pixel.
  344.  
  345. The routine will draw the image into your rastport using the best method available for the
  346. screenmode. CyberGraphics screens will have the data transfered as 24-bit directly, 256 colour modes
  347. will use an ordered dither to maximise quality from the 256 colour fixed palette, Ham8 will use our
  348. 18-bit colour mode, etc. If new display modes are added to photogenics, the DrawPreviewImage
  349. routine will be updated to take these into account.
  350.  
  351. Remember to free the preview with FreePreviewImage(giodata) when you've finished.
  352.  
  353.  
  354. EfxPrefs
  355. ========
  356. This is for preferences that you don't want requested every time. In general we don't use this
  357. much, but if you have options that aren't likely to be changed very often, then put the requester
  358. for them in here.
  359.  
  360. EfxAbout
  361. ========
  362. This routine will bring up the about requester when information is selected for your GIO. Put
  363. your credits, instructions or whatever in here..
  364.  
  365.  
  366. Arexx...
  367. --------
  368. If your effect takes parameters you'll need to support arexx. See the balance.efx code for
  369. an example of how to do this.
  370.  
  371. A string is passed to you in giodata->ArexxString. You need to parse the parameters from this
  372. string, so if you have two values you'll get a string like..
  373.  
  374. "150 190"
  375.  
  376. I'll leave how to split this up as an exercise for the reader, but if you're really lazy
  377. you can use our ParseRexx function (make sure you've got the pgsrexx_pragmas included and
  378. you've included the
  379.  
  380. #define PgsrexxBase giodata->PgsrexxBase
  381.  
  382. definition or you won't get at any of our library calls.
  383. (we use macros to reference most of the library bases off the giodata structure, this
  384. removes the need to re-open libraries, and cuts down the code size).
  385.  
  386. Here's the code:
  387.  
  388. LONG pointers[] = {0,0,0};
  389.  
  390. ...
  391.  
  392.     if((giodata->ArexxString) && (PgsrexxBase))        /* do we have a string? Do we have arexx? */
  393.     {
  394.             LONG array[] = {3, (LONG) pointers,
  395.                             PARSETYPE_INT,-255,255,
  396.                             PARSETYPE_INT,-255,255,
  397.                             PARSETYPE_INT,-255,255};
  398.         
  399.             if(giodata->ArexxError = ParseTemplate(giodata->ArexxString,array))
  400.             {
  401.                 giodata->Error = GIO_AREXXERROR;
  402.                 return(giodata->Error);
  403.             }
  404.  
  405.             rval=pointers[0];
  406.             gval=pointers[1];
  407.             bval=pointers[2];
  408.  
  409.  
  410.  
  411. ParseTemplate is pretty simple... There are four data types you can detect:
  412.  
  413.         PARSETYPE_INT,min,max,        return a number between min and max.
  414.  
  415.         PARSETYPE_STRING,                return a string
  416.  
  417.         PARSETYPE_ENUM,"OPTIONA","OPTIONB","OPTIONC","OPTIOND",0
  418.  
  419.                                             return a number for the string which matches the given options.
  420.                                             eg if you passed OPTIONC it would return 2.
  421.         
  422.         PARSETYPE_REST,                return the rest of the string.
  423.  
  424.  
  425. Note important:
  426.  
  427.         PARSETYPE_STRING copies the string into space you've already allocated and set the
  428.         pointer to in the array you pass.
  429.  
  430.         PARSETYPE_REST doesn't, it just returns a pointer to rest of the string.
  431.  
  432.  
  433.  
  434.  
  435.