I thought I’d write another stream-of-consciousness blog entry. Now that I am more-or-less finished with the Cinepan Player release (except for putting up a webpage), I am preparing to return to Sagelight development.
I can see that I am in a period of ‘re-tooling’ with Sagelight, and this is because the next section of Sagelight that I am writing is really transformative. Sagelight is a big, big program, and – like all big programs – needs to be revamped in various areas from time to time.
I’ll write more about that next time.
Writing Software for Me vs. Writing Software for Everyone
In this Programmer’s Blog Post, I want to write about the difference between writing software for one’s own use – or a technical use – and writing something that everyone can use.
I think this will shed some light on why things are done the way they are in programming environments, and a little bit about why Sagelight does some things it does, and why certain features do take some time (and thinking!).
The basic issue is that when people asked for me to put the ability to add one’s own panoramas into the Cinepan Player, that functionality already existed. But, it took me nearly 3 weeks to write the code that made it useful for everyone else.
That is to say, it took me almost 3 weeks to write what I already had in the Cinepan Player!
This is because when you develop something for your own use, it can be (and is) very different than developing it for a release-level piece of software.
Writing In-House Tools
When programming for various companies, you always first come into their set of in-house tools. Most of the time, these tools are programmed with scripts (or you’re just told by someone what to do, who was also told by someone, and so-forth), and nothing can really go wrong because it’s a strict environment. When it does go wrong it’s usually a major problem, but an adjustment is made to the code to fix just that issue, and then you move on. As I wrote in the last Programer’s Blog, this has to do with time and money and specifically not wanting to have to test an entire code base just for one problem.
Sometimes, these tools need to come out of the development department for use by other departments with users who aren’t programmers (such as marketing, or the UI design team). The program then needs to be a little more robust than it does for the developer – it doesn’t need to handle everything, but it needs to make sure it doesn’t hurt anything, either. Bugs that get in the way of the actual work to be done get fixed, where the other bugs just end up in the documentation with the notation “Don’t do that” with regard to whatever causes it (which satisfies us programmers greatly).
Note: I want to mention that this isn’t the way things should be and it really represents bad programming and methodologies. This tends to occur in a lot of companies because of the issues I talked about last time (i.e. money, time-constraints, not wanting to retest entire systems, etc.)
I’m really talking about the reality of it, as opposed to how its supposed to be. I also pointed out (in the last post) that this is what I’ve learned in building a huge project in Sagelight, i.e. “Don’t do that”, as stated above, but at a higher level so I don’t have to tell anyone else that when they use it, or program myself into corners (which I have on a couple things with Sagelight which – yes – means I will need to completely re-write those sections instead of growing them).
You’d be surprised at how many projects get thrown away and completely restarted because of this sort of thing, directly contrasted by an amazing scalability and growth of programs when you do it right from the start.
The Game Changes Significantly When Releasing Software to the General Public.
When releasing software to the public (i.e. consumer), every conceivable bug needs to be accounted for and tested (and you can never test them all) and – more than that – each potential bug or problem needs to be handled in the code (sometimes nested quite a few levels, which means it has to know how to get it back up the chain to the top level) and reported to the user in a way where it is understood what happened, so the user can either adjust his/her actions or report it to me in a way where I can figure out what happened.
Code such as the original Cinepan Player “Add-Your-Own-Panorama” code, where I know what to do and – more specifically – what not to do, suddenly has to deal with anything that might happen because I won’t be there all the time now.
A Great Example of a Bug I Didn’t Know to Test For
A good example of a bug I didn’t see – or even conceive to test – is directory names with a space. On my main system, \my root directory is something like “Users\Rob\CinepanDevelopment”, from which I specify everything I do to test the Cinepan Player.
When I moved the Cinepan Player to another computer to test, it promptly failed when I gave it a JPEG image to add as a Cinepan Panorama. It just wouldn’t load the panorama, and I couldn’t determine why this was happening.
Fortunately, I had the development system on that computer, too, and was able to quickly see that I made a mistake in the programming and that the cause was a space in the directory I use on this other computer, “Users\Rob Asus\CinepanDevelopment”.
On my main development computer, I didn’t test the Cinepan Player on any directory with a space in it. It turned out I was using a useless system call to establish the directory and the space was being seen as a terminator, so the path would become “Users\Rob” instead of “Users\Rob Asus\CinepanDevelopment”.
That’s just one tiny issue that comes up in the entirety of the Cinepan Player. Now, expand this to something like Sagelight, and this is where having standards and a very good overall OO structure starts to pay off – it’s still a huge amount of work to test conditions, but a good structure makes these errors easy to find.
Then expand this issue into someone else reporting it where I don’t know all of the conditions!
3 Weeks to Write What I Already Had Working, aka a Programmer’s Life (sometimes)
Here is what I had to do with the Cinepan Player tools in order to get them to work for everyone and not just me (where they were working fine).
I explained a little of this in the last blog post, but it’s interesting to see what sorts of things need to be done!
3 weeks of my work:
- Create an entire UI for adding images
- I already had a UI. But, it was plain and used specific and technical keyboard controls, such as ‘>’ to increase the angle, or ‘(‘ to decrease the horizon.
- I also had to go to the CMD level to process the output into a PGR file for the Cinepan Player. You could also exit the program without writing to the output file (too easily, in fact), and it was easy to do something that crashed the program – like specifying a low angle; all those things I know not to do because I wrote it.
- The UI needed buttons, a decent design, tool tips, and all of the code and options that I was using on the DOS command line
- Creating the design for the UI – as simple as it really is – took a day or so, all by itself, for various reasons (that is, UI design is not as simple as it looks, precisely because the point is to make it as simple as possible, at least without sacrificing functionality). That last point gets into Sagelight territory, where there is always a fine balance between making a UI that’s too simple (which does less) and a UI that’s too complex (but does a tremendous amount of things)
- Create an interactive ‘horizon tool’
- I was content with using the ‘(‘ and ‘)’ keys to adjust the horizon. But, I wanted to make it easy. So, I added an entire interactive, GUI based mechanism where you can simple move a line to set the horizon (then use the ‘(‘ and ‘)’ keys, or the buttons in the UI, to adjust the value). This made it much easier. I didn’t need it for myself, but it is definitely needed to a general release.
- OO the Command Line tools I was using
- I was fine with the command-line tools. But, they needed to be OO-based, so I could control them better and, particularly, get the error-reporting up the chain. The command-line based, non-OO tools simply just reported the error and escaped to DOS.
- When you write things for other people, not only do errors need to be reported more cleanly, but memory has to be cleaned up and processes shut down so you don’t leave little 0-byte files all over the place (where in a development directory, I don’t care at all about such things).
- Convert Command Line tools to GUI tools
- This was a big one, and I described in the last post that this cost me a couple days instead of a couple hours because I didn’t pay attention to some standards that really should be non-negotiable, even at a personal level.
- I was going to originally add the Add-Your-Own-Panorama functionality by giving you the main UI, but then making you use the command-line tools to create the actual Cinepan Image.
- I decided this was a bad – repeat, bad – idea. It was too to difficult. Now, these tools are run within the Cinepan Player, and are much easier to use (and, in fact, now you don’t even need to know about them), streamlined and (mostly) flawless.
- Between the OO conversion, making the GUI for them, and testing these tools this was 3 days of my time, at least. And, again, I already had these tools!
- Add multi-threading Lanczos resizing tools
- This was another big one. In the original release of the Cinepan Player, I sized all images accordingly because I just put them on the web and the Cinepan Player knew what to do.
- With adding the ability for the user to add his/her own images, though, this all changed. I needed to be able to resize the image in two ways:
- Very Fast and On-the-fly when the Cinepan Player loads your image. Now the Cinepan Player will upscale or downscale your image to make it fit what it wants – all as it loads the image.
- Because of this, it needed to be very fast. So, I ported the SSE4, multi-processor code from Sagelight for the task. I didn’t want to add 10 seconds or more to loading time, so it was important to get the fast Lanczos resize in, instead of using a C++ version that is much easier to handle!
- When creating the Cinepan Output Image. If your image is > 2600 vertical pixels, the Cinepan Panorama Creation tool will size it down for you. This is to keep sizes low for distribution, and you don’t get too much of an increase in resolution at higher image dimensions (though, you do get some, and I will be adding this ability later).
- When you create your Cinepan Image, it may tell you it resized your image. You can also see the progress as it does it. It is very fast (being the same tool as described above), so it doesn’t take too long, which gives the Panorama process a nice feel to it.
- Again, I really had these tools already, but I needed to put them into the Cinepan Player. There was another day!
- Create a APP13 layer to insert into JPEG Images
- I really wanted a way to post the JPEG images, either on Flickr or the upcoming CinepanPlayer.com website.
- I tried to add the information into the EXIF information, or just onto the JPEG, but that didn’t work out.
- So, I wrote a tool to insert the information as APP13 in to the JPEG image itself. This worked out very nicely, and since APP13 is typically used for layering and such in Adobe Photoshop, this is a good, mutually-exclusive place to place the information (because a Cinepan Image, by definition, wouldn’t have layers).
- This involved another day or so, of writing the code and testing. It was mostly about testing. Making sure I could upload to Flickr/other websites, and download the image and have it play in the Cinepan Player.
- I’m pretty happy with the results.
- Create a .JPG and .TXT format for the Cinepan Player
- I was happy with the PGR format. It encrypts the image and can come with a lot of information, such as the angle, description, thumbnail (for the Cinepan UI), etc.
- To post on the web – and to make it so you can post your own Cinepan Images – I needed to ship it as a JPEG image. The issue is that there is a lot of information the Cinepan Player wants. In the PGR file, it just has a directory of files.
- To make it useable (i.e. adding your own panoramas) for everyone else (not just me), I needed to support a JPEG format, which meant adding a lot of code to the Cinepan Player to look for the .PGR file embedded into the JPEG (instead of the JPEG embedded in the PGR).
- I also needed a .TXT format. A lot people may not want to alter their original JPEG images. Now the Cinepan Player can write out a simple .TXT file (i.e. MyFile.Cinepan.txt) that pairs with the .JPG file.
- When the Cinepan Player finds the .txt file (and the JPEG of the same name), it just translates the file in a different way.
- The .TXT file is made so you can edit it yourself.
- This was another section of code I needed to add – and test.
- Lots of little things not mentioned
- There are quite a few other things that tend to go unnoticed or forgotten in projects like this. Let’s see what I can think of off the top of my head.
- Refresh Button. I added the refresh button so people could download new Cinepan Panoramas and refresh the list without exiting the program.
- Get More Panoramas UI. I originally just had this go to a website. Quite a few hours was spent making this a full-blown UI to let you know a) where to go (i.e. Flickr or the main website) and b) where to put the images when you download them
- “No Thumbnail Available” Thumbnail. Now that everyone can add panoramas, this means more testing. One thing to test is whether or not the Cinepan Panorama Thumbnail is available. I purposely made it so you could strip the thumbnail in the .TXT file (to make it shorter; postable).
- Another hour or two was spent making the default “No Thumbnail Available” thumbnail, and writing the code to support it!
- Tooltips. I wrote the tooltips for all of the buttons, allowing you to hover the mouse to see what the function does
- Fluid Exiting. The release version allowed you to exit if you clicked a mouse, but sometimes exited the program. I went through and fixed all points to come back to the menu (or exit when in screensaver mode)
- Key Help Popup. I really wanted people to know what keys that can use when the Cinepan Player is running (such as increasing/decreasing speed). If you press ‘?’ when the Cinepan Player is running, then a nice-looking window comes up showing you the keys you can use.
- Set Image Directory. I added code so that the Cinepan Player has a set directory (set in the Installer). I also added an in-program button so you can change this directory. This wasn’t an issue when I was the only one distributing the panoramas. Now, with the ability for all to add a panorama, it is better to have this set directory.
- Fixed a Math Bug. There was a math bug affecting how the horizon was dealt with. I was working around it on my own, but it was important to fix this for everyone. This was very time-consuming, as this part is some weird math, actually.
- Fixed another Math Bug. This one was very confusing. Was finally able to fix it. I didn’t need it for myself, as I could just adjust the image in Sagelight to compensate. I needed to fix it for general release, though.
- This one was very time-consuming, costing me a 1.5 days. Sometimes the smallest bugs to do this.
- I once spent 3 days looking for a bug in a program. The cause? I was doing a ‘ror’ instread of ‘rol’. Still my favorite bug of all time!
- Screen refresh. I didn’t really care about that, but since I was really trying to make it as useable as possible for everyone, I added the code to make sure the screen gets refreshed when adding a panorama. I originally just had a key for it
- That’s probably the best stated difference between a tool one uses on their own vs. one that is released to the public
- That is… for me, a key was fine when the screen got a little dirty. For general release, though, this is unacceptable.
- And this is just off the top of my head!
- Write the Installer
- Writing the installer was also very time-consuming. Writing a proper installer requires a lot. You need to make sure everything goes ok, and when it doesn’t it needs to be reported and – because installers can write to anything or delete anything – very careful about how it backs out and what it is writing to!
- Logos, Artwork, etc. There’s also the UI, not to mention all of the icons, etc.
- Write the Uninstaller
- This also took a little time. The Uninstaller also needs to do a lot of work, and it needs to be very careful as it does it. This means a lot of testing!
- Write the help
- The help for the Add-Your-Own Panorama was time-consuming, as well. A lot of image examples and text. I learned a long time ago that it is important to write the help before you release the program; otherwise, it either never gets done or is completely lacking.
- Test, Test, Test
- Testing also becomes very important. The more bugs found and prevented, the smoother a program becomes. Plus, this is a program I am about to release on the Internet via Cnet, etc. The more bugs found the better!
- Testing is also very time-consuming, as all little cases have to be tested, and when a bug is found, this means going back to the development system, recompiling, re-testing, changing version numbers, re-packaging the installer, and re-uploading.
- Then, when another bug is found (because you didn’t see this new one yet), the entire process repeats. Sometimes it can be 2-3 days before you feel comfortable telling the world about your release!
The Cinepan Player is About the Size of the HDR or Bokeh Function in Sagelight
The above list is just for the Add-Your-Own-Panorama function in the Cinepan Player, which took nearly 3 weeks. Seeing the list above, perhaps this makes more sense.
The Cinepan Player overall (i.e. the entire program) is about the same amount of work as the HDR or Bokeh functions in Sagelight. That is to say, the Cinepan Player – which is a large project by itself – is about the same size and level of work as only one of the major functions in Sagelight.
This is one of the things the Cinepan Player showed me about Sagelight Image Editor – just how extensive and feature-rich things like the Bokeh, HDR, etc. really are when you think about them as separate features or programs.
In some ways, I really should split Sagelight into separate programs to give the HDR, Bokeh, Light Blender, Power Curves, Power Tools, Smart Light, and a host of other functions, some more visibility, as I do think the level of effort and work embedded in these individual functions do get overlooked when they are packaged as just one function, respectively, in an overall package that has many such functions.
But, that’s life, I guess, as I do prefer to have these huge features accessible in one package as they are now in Sagelight.
This gets me back to the idea of why the Cinepan Player was such a great project, and how it was not only a good distraction for a short time, but also that it showed me how to approach the next leg of Sagelight.
I’ll get to that in the next post.