Jumping off from my last post about getting images into Altium Designer, it was surprisingly difficult to do in CircuitMaker.
After three days of attempting a few different approaches, I have one that I’m quite happy with. Conveniently, this is pretty good at getting images into EAGLE as well, at least as good as the built-in ULP.
If you’re just here for the solution, scroll way down and read the paragraph about the brd-builder.py script.
The first approach I started with, after drawing some pretty pretty pictures, was to attempt to load them into Altium in the same fashion as before.
These images were way larger and more complicated than the previous experiment, however, and the Delphiscript chewed on it for three or four hours before silently failing. Even if it had worked properly, I’m not particularly happy about being dependent on the expensive professional tool to work with the hobbyist one. So I delved into it.
Here are the options and approaches I took:
- Importing DXF files in Circuitmaker is possible, but largely unsatisfying. The importer splits up the original paths into discrete arc and line segments. This is great if you want to draw outlines, but only that. Lack of fill options or the ability to merge these objects make it mostly useless for my purposes.
- Using “region” objects. Going into the options of one of these objects yields a list of points and coordinates, and import/export options. So I wrote a converter to massage SVG files into the proper CSV format. It’s all in svg-parse.py. It’ll take an SVG file, and convert each individual object into a CircuitMaker-compatible CSV file. From there, you can create a region in CircuitMaker, open its options, and import one of the CSV files.
This is pretty good, and results in native objects that are speedy to move around. There are some caveats, however:
- You must do this for each object, making it labour-intensive for complex canvases
- Curves are not supported, so it is first necessary to follow the “Add Nodes” and “Flatten Beziers” steps described in the import-dxf EAGLE plugin.
- Attempting to hijack the clipboard was the next experiment, read-clipboard.py. Region objects can be copy-and-pasted between documents, so I wanted to take a look at what that data contained, and maybe silently insert my own. This never really worked properly, and I abandoned it quite quickly. It was a hacky approach, anyway.
- A quick search on reverse-engineering Altium’s file format brought up this starter (by way of Hack-A-Day). Although very abbreviated (the goal of that guide is to provide a methodology, not to reverse the file format), the page was more than enough information for me to write a Python script to open and dump the contents of the CircuitMaker-formatted OLE document. So in ole-extract.py, I got as far as grabbing a library document and extracting and splitting header/data information into a folder. Realised at this point that the libraries I was using would have a difficult time repacking the streams into one OLE document. Not to say it isn’t possible -it totally should be – it’s just rabbit-hole I don’t particularly want to go down at this time. This is still interesting in that it should be a working barebones Altium and CircuitMaker file reverse engineering effort in Python, which hasn’t been done before.
- Importing EAGLE files works really well. First, I imported a file that contained an image, and it looked great, worked great in CircuitMaker. I poked around with how that image was created in EAGLE, and it looks like it was just made with the built-in “Import Bitmap” ULP. What it does, is scan along each horizontal line, creating a one-pixel-high rectangle in the filled area. Repeat for the entire image.
Okay cool. That sounds really simple. Problems with that:
- It doesn’t alleviate my allergy to using 3rd-party software as an intermediate step
- If my image is over the 3 inch (or whatever) size limits of EAGLE free version, I’m hooped
- The ULP script seems to choke on images randomly
So what I did instead, is take a dummy EAGLE file, and stripped it to the bare-necessities required to load. It’s an XML format, so while this is the fourth file format I’ve had to parse in this whole process, it wasn’t too hard. With this dummy file, my final and greatest script, brd-builder.py, grabs a bitmap file, converts and then injects it directly into the EAGLE file, giving you a proper output, no EAGLE install required. CircuitMaker can then easily import this via the File->Import menu.
Input images need to be a 1-bit BMP file. In Photoshop this is done by converting to grayscale in Image->Mode->Greyscale and then converting to bitmap in Image->Mode->Bitmap. In GIMP, this is done through the menu in Image->Mode->Indexed. Then save as BMP.
Before running this script, open it up and then modify the desired variables – inFile, outFile, layer, and scale. They should be fairly self-explanatory. Scale in my application was found by guessing until it fit my board, due to the resolution I drew my image at.
This was a fun detour. That’s good, because spending time to make tools for your tools can be very frustrating. The last tool in particular works great for me, but If I were to develop a robust tool that anyone could use, there are a few more avenues I would attempt to pursue first:
- In the Hack-A-Day link posted above, one of the comments mention being able to just open OLE. They turned out to be using 7zip, which supports that format natively. Coincidentally, I found a portable 7zip executable in the CircuitMaker folder. It’s possible that they’re using this for encoding their documents. It would be fun to write an executable shim with the same filename that invisibly passes arguments to the original 7zip program, but logs it to file as well. Will also look into better methods for doing this – Process Explorer, or getting the OS to hook WinDbg might be possible here
- Failing that, writing and testing code to modify the OLE document stream and then repack it into a format that CircuitMaker can read seems logical
- The native importers in the CircuitMaker all have IWZ extensions, and from the binary data seem to be x86/64 executables. Google says these might be installer files. Along the same lines as the executable shim/wrapper above, figuring out how these work and writing my own would be fun.