Robert Inventor


Home Music 3D Animations Utilities Code Search Forums About Contact Accessibility
Mem Leak Check
Play Midi Lib
Com Ports Monitor
Win Ming
Pop Pal Fast
Gle with time out
Time64

Win Ming

19th July 2003 (update)

Intro, Downloads, Intro to the library, Calling windows dlls from other languages, Updates

Intro

Ming is a library of routines primarily used for creating Flash Movies in PHP. However it also has bindings in other languages such as Perl and C++, and the code itself is written in C.

Here is the Ming project page:

As of writing this, there is no version of it available for Windows, though there was one previously according to the project page and may one be avalable again at some point.

This DLL is a partial port of the library to Windows which I did for a particular purpose. It does include the complete library. However I have only tested some of it and only thoroughly tested the parts that I have needed particularly myself.

It can be called from C programs. I'm told the C++ wrappers don't work so if you program in C++, your best bet may be to make a C module and call it from that. It is now way out of date and newer Ming features can't easily be added to it. But does continue to fulfil its original purpose and may be useful to some which is why it is left up here.

If you have any questions about this port, or suggestions, contact me at Robert Walker, support@tunesmithy.co.uk

PLEASE NOTE - THIS PORT IS OUT OF DATE

This port is now well out of date, as you will see from the date at the head of this page. It is based on Ming 0.2. The new Ming 0.3 beta has many features such as unicode font support and options to load swf files. This port doesn't have that. Also this port has been incomplete all along as it doesn't currently support actions or the Ming C++ wrappers. It is probably best used in C or called from a C module in your program. This port is not actively supported right now. Also - warning - the new Ming 0.3 uses different structures and declarations from 0.2 and so if you want to add a new feature from 0.3 to 0.2 it probably won't work to just copy / paste the code - the easiest method is probably to port it all again from scratch even if you just want to add e.g. unicode support or the swf file loading feature.

I may be able to return to this perhaps some time next year, but can't say for sure. Sorry about that - I get asked about this regularly so there is clearly a demand for the port. When I did this last time then the Ming development was temporarily on hold so had no-one to consult about it - so none of the changes I made are incorporated in the main Ming library and much of the work needs to be done again to re-port it. And I've no idea how you set about porting the actions or getting the C++ wrappers to work. I hardly code in C++ at all so am not able to answer questions about C++ wrappers.

I can answer some questions if they are connected with the aim for a program to be able to write directly to a swf file to create simple animationframe type movies using some of the most commonly used Windows 32 GDI calls. That works fine with Ming 0.2. I can also answer questions about how my Windows GDI resembling calls interface with Ming and about how to use those calls in your programs. Those are the only parts that I have worked on and that I am reasonably confident about.

Robert

END NOTE.

The particular aim I had in mind was to be able to call Windows graphics calls such as Polygon, PolyPolygon, LineTo etc from a C program and translate them directly into vector graphics for Flash movie frames. This is achieved with this port of the Ming Library for some of the most commonly used GDI calls. You select a movie into your graphics context, then it uses your currrently selected brush and pen to draw the shapes. You call a routine in the library to advance to the next frame when your current frame is finished. You need to include wrapper routines for your program to call instead of Rectangle, Polygon etc These will draw the polygon as usual normally, but will call the WinMing library to draw the shapes into a Flash movie frame if you select a movie into the hdc.

Here we have a couple of example movies generated using it:

 

For a larger scale view: Sunflowers, and Cube Star

As you see, it works fine when called from my program Virtual Flower for the routines I used - and they have had a pretty fair work out :-). I have also tested many of the other options in the library, though not so thoroughly - you will find tests of them in the zip. I haven't tested the sprites or actions at all and they may well not work yet. The winming zip doesn't include the PHP Perl or C++ bindings - get those from the original zip via the Ming project page:. The bindings aren't tested with this dll. If they work let me know and I'll add a note here to tell any interested users that they do.

Note that though these movies are in 3D actually all the drawing to the flash movie is done in 2D and the movies were made by drawing the entire shape anew for each frame. The conversion of the 3D shape to 2D polygons is done in my program, and it had some limitations as I note below. The Winming library is 2D. Would be nice if it could be extended to 3D - the 3D Flash generating programs you can get nowadays suggest this should be possible, but I have no idea about how one would set about it.

Another thing one can do with this library is to make animated jpegs or pngs by using them as frames in a flash movie. You do that by drawing a rectangle set to the extent of the window and then you fill it with a jpeg or png. The test.c file in the source code zip has example jpeg and png filled squares one can use as a basis for making such a movie. You can see some made using this library elsewhere on this site, e.g. this Flash animated jpeg. You can also add mp3 sound tracks to your movies.

As an extension to Ming, WinMing is open source, released under the Gnu Lesser General Public License. In its essence, this means you can use it with commercial programs (as I have done as a shareware developer). The only requirement really is that you have to contribute any modifications you make of the source code for Ming itself back to the project. There is no requirement to make the rest of your own source code available - that is a requirement of the stronger GPL..

Note that I have also added my own MemLeakCheck to the zip as it was needed for Png2dbl and useful for checking Ming itself for memory leaks (a particular issue for windows programs). MemLeakCheck is free source (and also quite short and simple in concept) - use it as you wish, as you might use a demo program in a c programming book..

top

Download

This zip includes the dll, the lib file for the linker to use, and the header. This is all you need in order to use the library from your programs.

winming.zip [84 KB]

You can fill shapes with jpegs or pngs in Ming. The jpegs can be used just as they are, but png files need to be converted to dbl files first for the library to read.

Here is a build of the png2dbl application as a dll so that you can call it from your app to convert pngs to dbls. It includes the .lib and .h files. It includes an exe version of it too which you can use from the command line - this is an up to date version of it. It also includes the zlib and libpng13 libraries which it requires and a test png file. The png2dbl dll is thread safe - only converts one file at a time and if several threads try to convert them at the same time then it will enter an efficient busy wait (using only a few assembly language instructions per time slice) until the library is ready.

png2dbl.zip [232 Kb]

Here is the source code for WinMing as an MSVC 6.0 project:: winming_1_0_0.zip. [757 KB]. You need this if you want to build the dll yourself or to make changes to it.

It is larger than one might expect perhaps, as it also includes the the libs and dlls png2dbl it needs, and also some test jpeg, mp3, fdb and png files so you can run the test programs straight away - and also the command line program swfdump.exe which one uses to dump the contents of a swf file in text format so that you can examine it. The mp3 is a highly compressed one mp3 of one of my pieces which was originally inspired by noises a coach makes as it goes along so the mp3 artefacts are entirel appropriate :-).

Here it is again without all those extras: winming_1_0_0_small.zip [431 KB]

I have left out the Perl, PHP and C++ bindings - get those from the original library. They aren't tested at all in this port yet. But if they work let me know and I'll add a note here to say so.

Also here are a some fonts converted from Flash to fdb already (from the Ming Perl How to and examples site): fonts_fdb.zip [178 KB].

top

Intro to library, Calling the Dll, Calling windows dlls from other languages

Intro to the library

Well the part of the library that is tested so far is the Windows interface for GDI calls. For the listing of routines available, see the end of winming.h

So this explanation will particularly focus on its use for Windows programmers.

You use them somewhat like this:

void MakeSWFMovie(char *szFileName,int width,int height,int frames_per_sec,int nframes)
{
 SWFMovie movie = WinMing_StartMovie(width,height,frames_per_sec,nframes);
 HDC hdc=GetDC(NULL);// hdc for desktop
 HDC hDCForMovie=CreateCompatibleDC(hdc);
 int iframe=0;
 ReleaseDC(NULL,hdc);
 if(hDCForMovie)
 {
  WinMing_SelectMovie(hDCForMovie,movie);
  for(iframe=0;iframe<nframes;iframe++)
  {
   // gdi calls
   //

   SWFMovie_nextFrame(movie);
   WinMing_RemoveAllDisplayItems(movie);
  }
  WinMing_UnSelectMovie(hDCForMovie,movie);
  WinMing_CloseMovie(movie,szFileName);
  DeleteDC(hDCForMovie);
 }
}

The idea is - start a movie. Set the width, framese per second and total number of frames. Then create an hdc, and select the movie into it:.

 SWFMovie movie = MingStartMovie(width,height,frames_per_sec,nframes);
 HDC hdc=GetDC(NULL);
 HDC hDCForMovie=CreateCompatibleDC(hdc)
 int iframe=0;
 ReleaseDC(NULL,hdc);

Then if this has been successful, select the movie into the hdc, and loop around to draw all the frams you need.

if(hDCForMovie)
{
  WinMing_SelectMovie(hDCForMovie,movie);
  for(iframe=0;iframe<nframes;iframe++)
  {
   // gdi calls
   //
            

The hdc here isn't actually used for drawing at all any more. All your code will do is to select pens and brushes into it - and then the Winming library can then interrogate the hdc to find the current brush or pen colour and what pen width to use.

So, in order to draw to the movie instead of to the hdc, use wrappers for supported gdi calls such as this one (wrapper routines to use are included in a comment at the end of the header):

BOOL PolygonOrWinMing_Polygon(HDC hdc,POINT *pts,int npts)
{
 if(WinMing_GetMovieForHdc(hdc))
  return WinMing_Polygon(hdc,pts,npts)?TRUE:FALSE;
 else
  return Polygon(hdc,pts,npts);
}
            

Here WinMing_Polygon actually returns the polygon's display item - this is a variable, a kind of a handle, which you can use in order to rescale your polygon or rotate it etc after you have drawn it if you want to get into Flash specific programming. E.g it can be used to efficiently rotate a polygon or morph it to another shape over a number of frames without the need to redraw it again for each frame.

Replace Polygon(...) by PolygonOrMingPolygon(...) everywhere in your code, and similarly for other supported GDI calls.

Now, if you have a movie selected into your HDC then all your drawing calls will be painted to frames of that movie. If no movie is selected into it, then they will just draw as normal.

Note - the library routines don't take account of mapping modes at present - this assumes you are using the default mapping mode. x increasing left to right in pixels and y from top to bottom. It would be a straightforward modification however to interrogate the hdc to find the current mapping mode and take account of it by calling GetMapMode, GetViewportOrgExe, GetViewportExtEx, getWindowOrgEx, GetWindowExtEx etc. as needed to find out how to transform the coords before drawing the shapes..

You end a frame using

   SWFMovie_nextFrame(m);
   MingRemoveAllDisplayItems(movie);

If you want the animation to pause, simply repeat the frame by calling SWFMovie_nextFrame(m) repeatedly - do this before the call to MingRemoveAllDisplayItems(movie).

Then finally when the movie is done, call

  MingUnSelectMovie(hDCForMovie,movie);
  MingCloseMovie(movie,szFileName);
  DeleteDC(hDCForMovie);

Here szFileName is the file to save the movie to. You only need tospecify this at the end as this is the point where all your gdi calls get saved to make the movie.

There are so many GDI primitives in Windows, only a few of the more common ones are given wrappers here. Basically the ones I happen to have needed most so far. Some of them probably can't be translated so directly as these ones.

By way of example, I'm particularly interested in dealing with clip regions. They are useful for 3D drawing in Windows (if you don't mind too much about speed) - - you can use them to paint on part of the drawing area only.

If you look at the sunflower above you will see that the stalk isn't always quite centrally placed where it meets the flower head, depending on the position of the flower. That is because the point of it is actually within the head of the flower. and should be clipped. With the CubeStar movie, the stars should intersect with each other as they unfold instead of lying one on top of each other all the time as they do now.

This is quite a complex thing to do as you could have several shapes overlapping on each other in a spiral or whirlygig fashion, A in front of B, B in front of C and C in front of A. In windows you can create a mask for A and mask it by the part of B which is in front of it, then draw A, then remove that mask, then mask B by the part of C in front of it and draw B, and so on - you can do this in Windows using clip regions. I'm not sure whether the Flash masks can be used in the same fashion. (If they can be sure to let me know :-)).

top

Calling the DLL.

To add a dll to your Windows program you just need to include the dll somewhere where it can be found - usually either in your PATH - e.g. the System folder, or else in the program's own folder. Add the .lib file to the linker options. In MSVC 6.0 you do that from Project | Settings | Link | Object / Library modules. You only need distribute the dll with your program and not the .lib file.

top,

Calling windows dlls from other languages

When one calls Windows dlls from some other language, one needs to be aware that the functions in the library are declared as __stdcall

Here is the summary for __stdcall from the documentation:

Argument-passing order Right to left.
Argument-passing convention By value, unless a pointer or reference type is passed.
Stack-maintenance responsibility Called function pops its own arguments from the stack.
Name-decoration convention An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number
of bytes (in decimal) in the argument list. Therefore, the function declared as int func( int a, double b ) is decorated as follows:
_func@12
Case-translation convention None

Another thing to be aware of: long and int are both four byte integers in a 32 bit platform such as Windows. Only short is two bytes.

If you need to know the decorated function names for a dll to call them, you can figure them out from the convention and by looking the types of the arguments up in the various headers, but probably the easiest method is to just open the dll in Wordpad. You will find them all there at the end amongst the binary data in the file.

top

Updates

Contact e-mail:

Robert Walker support@tunesmithy.co.uk

19th July 2003:

Includes latest version of MemLeakCheck.c. Note though that you don't need to free memory on exit from a program in Windows as Windows will do it automatically and I was wrong about my earlier remark that one needs to do this. See discussion at: Code Project: Mem Leak Check Article

Also - the download links weren't working - made small changes in the names of the files and forgot to update this page accordingly - fixed.

15th July 2003:

Realised the last upload of pn2dbl dll mightn't be thread safe always. Now the routine is placed within a block which only one thread can enter at a time This means only one thread can convert a png to a dbl using the library at the same time. Other threads using the library wait in an efficient busy wait (using a few assembly language instructions only per time slice then surrendering the rest of their time slice) until it is their turn..

14th July 2003:

Made pn2dbl dll thread safe for use in multithreading environment.

In the original upload I forgot to switch on the memory auto free in the release png2dbl dll and .exe file - fixed.

New vesion of MemLeakCheck.c included in the library - see my MemLeakCheck page for details of it.

First release 10th July 2003:

Augmented all routines that use FILE * arguments by ones with char * arguments for the file names.

This is because in Windows you can only pass a file pointer to a dll if the dll and the application use the same C run time library. Unfortunately, there are many versions of the C run time library. . The libraries can be single threaded or multi-threaded, also static or dynamic, and there are also separate versions of them for debug or release builds. Finally different versions were used for apps built using MSVC 4.0 or earlier: Potential Errors Passing CRT Objects Across DLL Boundaries. In order to pass a file pointer to a DLL, the application and the dll must use the same identical C run time library. The normal symptom of mixing the versions seems to be an access violation when the pointer passed to the DLL is used.

So, it seems best to just side step the whole issue and pass file names to the dll instead.

So, you need to use:

DLL_A int DLL_B SWFMovie_output_for_file_name(SWFMovie movie, char *szOutputFile)
DLL_A SWFDBLBitmap DLL_B newSWFDBLBitmapForFileName(char *szFileName);
DLL_A SWFJpegBitmap DLL_B newSWFJpegBitmapForFileName(char *szJpeg);
DLL_A SWFJpegWithAlpha DLL_B newSWFJpegWithAlphaForFileName(char *szJpeg,char *szAlpha);
DLL_A SWFSound DLL_B newSWFSoundForFileName(char *szname);
DLL_A SWFDBLBitmap DLL_B newSWFDBLBitmapForFileName(char *szFileName);
DLL_A SWFFont DLL_B loadSWFFontFromFileOfName(char *filename);

Added buffered file output. Instead of using fopen(...) and fclose(..) you use fopen_Buf(...) and fclose_Buf(..). The buffer gets flushed when you close a file and it uses 10 KB buffers. The result is that the file saves should be faster.

If you want to use file pointers yourself, the solution is to set your own functions for file input and output. You open the file yourself, pass the pointer to the library, and then get the library to call a routine back in your own program to do the actual writing of the file. This sidesteps the issue again because the pointer only gets used in the place where it originated so is still valid. I added some routines to let user set a callback for file output.

Added

MingRemoveAllDisplayItems(m);

which you can use to clear the movie to have a clean slate before you start the next frame.

Then - there were a couple of eccentricities in the MSVC 6.0 compiler that needed to be accoutned for.

ShapeRecord newShapeRecord(SWFShape shape, shapeRecordType type){
...
  return shape->records[shape->nRecords-1];
  shape->nRecords++;
  return shape->records[shape->nRecords-1];
  // here the original was
  // return shape->records[shape->nRecord++];
  // This causes an exception in Windows. I think shape->nRecord
  // probably gets incremented before the function returns.
}
static int readUInt16(FILE *f)
{
 byte b1=fgetc(f);
 byte b2=fgetc(f);
 int iret=b1 + (b2<<8);
 return iret;
 // because in  the release build the original doesn't work:
 // int iret = fgetc(f) + (fgetc(f)<<8);
 // MSVC 6.0 optimising compiler sets the second fgetc(f) to have same value as the first one
 // - doesn't read it again
 // return iret;
}

Then here was a mtter of a memory leak to fix - one inherent in the design of the library, not a flaw in it.

If you make new shapes, etc to add to the movie then though they have destructors, they don't get automatically freed when you close the movie. You have to free them yourself. Also you can't do that until the movie is finished. So you have to keep track of all the objects you have made and free them yourself if you want to avoid a memory leak.

Presumably this isn't an issue in Linux - because I gathe the memory gets freed anyway when a program exits. However, in Windows you have to be careful to free all memory you use yourself because the operating system doesn't do it. Even after your app closes, any unfreed memory it allocated hangs around, reducing the amount available. If this happens often enough, eventually the user gets out of memory messges when they try to start any program up, and has to reboot their computer.

Probably there is a better way to do it - but what I did is to make automatically updated lists of all the shapes and fills that get made during the movie - and then when you destroy the movie you can clean them all up using Ming_clean_up(). This gets called automatically in MingCloseMovie(m,szFileName) in the Windows GDI calls way of doing things. I've only done these for the things I needed them for and it is possible that there may be others that need to be added for other ways of using the library.

top

Disclaimer
Acceptable Use Policy
Special Offers
Contact
Copyright
Privacy
 
Site Designed with advice from Sojo Media (Thanks!)
© Robert Walker 2008
tool tips by overlib
Robert the Inventor's programs
By Robert Walker
support@robertinventor.com

NEW metronome software - Download Bounce Metronome Pro with bounces and conducting patterns to help you stay in time.