Sep 28 2011

RICcreator – September update

Category: Lego,Mindstorms,RICcreator,SoftwareSpiller @ 17:56

Not much have happened on the SVN repository, this is the pain of not having an Internet connection and not being able to do local commits with SVN…

Overview:

  1. Offset added in nxtCanvas
  2. VarMaps and Polygons
  3. Command line improvements
  4. Adaptive thresholding
  5. Loading RIC files from a byte stream
  6. Download

Offset added in nxtCanvas

A huge update has been made to nxtCanvas which emulates the NXT screen. And offset to the drawing commands have been added, so instead of always assuming the lower left corner to be (0,0) it can be anywhere on the canvas.

It is not intended to be changed manually however. The reason for adding this is because you get some ugly side effects when automatic resizing of the canvas is turned on. If you use PointOut(-1,-1) with automatic resizing turned on, the canvas is expanded and the point is drawn at (0,0). However if you do this a second time, PointOut(-1,-1) will point to another pixel than the previous call which might not be desireable.

However a more serious issue was in the editing GUI for nxtCanvas. If you for example tries to draw a line it shows a preview before actually drawing it. When you move the cursor outside the canvas it automatically resizes. However if you moved the cursor to a negative coordinate it would still keep the canvas in the same place. If you tried to draw a line to (-10,-10) this command might have been issued 5-10 times because of the live preview, causing the canvas to be rapidly expanded. Because of this the live preview has until now had automatic resizing turned off, only turning it on just before the user stopped drawing.

While this is finally working as intended now, adding that offset was a pain since it caused pretty much everything drawing related to break.

VarMaps and Polygons

VarMaps have been implemented for a long time, however it didn’t have an editable GUI. And since this is one of the most important elements, RICcreator have been pretty much useless so far. The reason that I didn’t add it until now was that I was not satisfied with the way it is implemented in nxtRICeditv2 and wanted to do this differently. However I didn’t get any ideas on how to improve it so in the end I just implemented a similar design.

VarMaps and Polygons have been implemented using the same datatype in RICcreator, so the GUI for them both is the same.

With this done, RICcreator now supports editing every RIC opcode in the enhanced firmware. Only thing lacking now is implementing fill_shape for polygon and the special copy options for RIC fonts.

Command line improvements

RICcreator supported one parameter, a filepath to a RIC file to open. You can now open several files at a time by specifying more than one filepath.

A completely new addition is converting files through the command line. By using the “-convert” parameter you can convert RIC files to PNG. It is used like this:

RICcreator -convert FROM_FORMAT TO_FORMAT filepath

If you want to convert “circles.ric” to png you use it like this:

RICcreator -convert RIC PNG circles.ric

This will create “circles.ric.png” in the same folder as “circles.ric”.

Formats are:

  • RIC: ricfile, can be used for both input and output
  • PNG: PNG image, only output
  • C: C header file, only output

RICScript will be added when implemented. Currently conversion is done with all RIC parameters set to 0, if anyone have a good idea to how these could written on the command line speak up!

A note on the PNG export using the command line is that the nxtCanvas is set to 0x0 and then every draw command resizes the canvas to fit everything. So the resulting PNG will not be 100×64, it will be sized to contain everything drawn and the (0,0) point.

Adaptive thresholding

Thanks to the material Linus from Mindboards gave me I have now implemented adaptive thresholding in the import image dialog. I have written the algorithm myself so it is a bit slow right now.

The improvement with using adaptive thresholding instead of global ranges from almost nothing to quite a bit. However it is more difficult to get good results with it so for now global thresholding is default.

Global vs. Adaptive thresholding comparizion

Global thresholding to the left, adaptive thresholding to the right

Loading RIC files from a byte stream

It is now possible to load a RIC file from an array internally. This makes RIC loading much more flexible. I cover this more deeply in another post though. The most noticeable change this made for RICcreator is that the default RIC font is now embedded into the program and that it is possible to convert the file into a C header.

Download

Pre-Alpha revision 130: RICcreator rev. 130 – win32.zip


Sep 28 2011

Loading RIC files from a byte stream

Category: Lego,Mindstorms,RICcreator,SoftwareSpiller @ 17:48

riclib have until now read RIC files directly from a file stream. This is done using a distributed approach, each nxtVariable is passed a file stream pointer and loads the data it needs by itself.

A ricfile in riclib is made up by an array of ricObjects which each contains a list of nxtVariables containing the data. When a ricfile starts loading, it reads the first 4 bytes which contains the ricObject header and creates the ricObject which have the same opcode as specified in the header. That ricObject read funciton is then called, loading each of the nxtVariables it has. The whole process is then repeated untill it is not possible to read another header.

Adding a second source to read from would require an extra read command to be added for each nxtVariable which would be a lot of work.

A file can easily be converted into a char array, so I could just drop direct file reading and rewrite every function to read from a char array instead. Actually, I should have done this from the start. (I didn’t because this would require 3 paramters to be passed each time, the char pointer, the current position in the array and the total lenght of the array.)

I decided of some reason to do a more complicated approach. I added a abstract base class nxtIO which is used by nxtVariable to read and write to RIC files. I have then added to classes which inherits nxtIO, nxtFile which implements file IO and nxtStream which implements IO on a char array. The advantages of doing it like this is that I only need to pass one parameter, the nxtIO pointer, and that it is possible to add several other types of IO without redoing the reading functions in nxtVariable. The disadvantage is that it is more work and that I probably will not need to be able to read/write from anything else than char arrays anyway…

The reason behind using byte streams

One of the key goals with riclib and the reason it is keept seperate from the GUI code is that it should be easy to use it to extend other applications to use RIC files. However since it needed a RIC file containing the font to use with TextOut to be located together with the exe this could complicate matters for the application developer.

So one of the key benifits with reading from a byte stream is that a RIC file can be embedded into the exe. IO to a byte stream can be used in the other direction too, in order to create a C header file containing a RIC file to easily embed the RIC file into C/C++/NXC programs. (quick implementation done)

Another important reason is that when you use riclib in other applications you might not be able to read/write directly from/to a file. Consider that you want to upload and download RIC files to the NXT. The interface functions will undoubtly use byte streams instead of files. (I will add this feature as soon I as can figure out how to do it.)

Another case would be using riclib together with the Windows Shell. Once I figure out how to create a COM module I’m planning to add RIC support into Windows Explorer. While supported, Microsoft discourages using filepaths and suggests accepting and using bytestreams instead.

Example

I’m currently creating an image viewer using QT. QT already supports most image formats like JPG, PNG, BMP, SVG and more, but allows you to create plugins to implement special fileformats. So I created a plugin to extend QT to support ricfiles using riclib. This will not just extend my application, but every QT application using QT’s inbuilt image functions. (The application and plugin will be posted in the near future.)

I will not go into depth about how this is done however one of the key aspects is that QT is not using filepaths, but its own QIODevice class which does a similar task as my nxtIO class. I could create a sub-class which inheriths nxtIO and read/writes to a QIODevice, but I took the easy solution and just used the QIODevice to read the whole file in one go and use nxtStream instead.

QByteArray data = device()->readAll(); //Read all bytes in QIODevice into data
nxtStream stream( data.data(), data.size() ); //Create a nxtStream using data
ricfile file;
file.read( &stream ); //Read the RIC file

nxtStream takes a char pointer and a int holding the size of the array. What is left is just drawing the file:

nxtCanvas canvas;
canvas.set_auto_resize( true );
file.Draw( &canvas );

The canvas is created at size 0x0 with auto_resize on. The RIC file then draws on the canvas, expanding it as needed.

The next step is to convert the nxtCanvas into an image format the application supports which is normally rather trivial. One thing to remember is that (0,0) is located in the lower left corner in nxtCanvas where it is most often located in the upper left corner in other formats.