Runtime Revolution
 
Articles Other News

Quick Apps with Rev:
Can Revolution Make You More Fit?



Or, How I converted a graphic file and still had time to work out

by Bill Marriott


When people think of "programming" they often imagine large projects such as what's required to write a productivity application, game, or database project. That's because most languages are so complex that it often makes more sense to do a task manually – or not at all – rather than take the time to write something that can do it. Not so with Revolution. The natural, English-like language we use for scripts makes it a snap to tackle simple programming projects that can solve everyday problems.

This "just in time" nature of Revolution came in especially handy for me recently. A few weeks ago, I started a daily exercise program and picked up one of those fancy watches that can read your pulse and monitor your workout activity. It has a bitmapped display; similar to cell phones, it has an ability to display a "logo" or "wallpaper" and comes with a utility to create and upload your own.

I was really excited about this, because I wanted to replace the standard logo with something more personal and motivating. The problem is that the utility used to create and upload these images to the watch is hardly PhotoShop. While you can save and load images in its proprietary format (PMB) there's no way to load external files, such as PNG or BMP. The drawing tools basically give you the ability to turn individual pixels on and off and little more. I would be able to create custom logos with this tool, but it would be time-consuming and the results might not look very good.

The watch's included logo-editing software isn't very flexible.

My first step was to search the web to see if someone already had something that could convert files into the needed format. To my surprise, I actually found a great web page on the topic at: www.martinet.nl/articles/20050524.html

The author had the same goal I did. He not only provided a web-based utility to provide the conversions, but also explained the PMB file format and provided PHP code for how he does the conversion. There was a problem, though. He had a different model of watch, which offered a much smaller region for the bitmap logo. His code checked to make sure the image was small enough to fit his watch, so I couldn't use his web page to convert bitmaps that fit mine.

I suppose I could have tried to make my own web page based on his code sample but that would have taken a lot of time, because the snippet just provided the conversion function, and none of the other stuff that's needed to accept an upload and put the results into a form field, etc. To accomplish this, I'd need to know HTML, JavaScript, and PHP reasonably well. I didn't want to spend hours trying this out and debugging it. This is supposed to be about improving my physical well-being, not enhancing my geek credentials!

Revolution to the Rescue

Nevertheless, the author had saved me a lot of time. He had already studied the PMB file format and discovered it was a very simple notation of the pixels that needed to be turned on and off, column-by-column. Working left-to-right, the pixels were represented as a binary number, then converted to a decimal number, one per line.

Columns of pixels are seen as binary numbers, which are converted to decimal values in the PMB file.

The file format was pretty simple to understand. Then I looked at his PHP code. Now, PHP is one of the most widely used languages for dynamic web pages because it's relatively easy to learn, and I've used it before. But this one had me scratching my head. I'll reproduce it for you here:

function image2pmb($imgLoc){
if ( function_exists('ImageCreateFromPng') )
{
$imginfo = getimagesize($imgLoc);
if ( $imginfo )
{
if( $imginfo[0]>0 &&
$imginfo[0]<50 &&
$imginfo[1]>0 &&
$imginfo[1]<50 &&
$imginfo[2]==IMAGETYPE_PNG )

{

$img = ImageCreateFromPng($imgLoc);
$pmb = '[BitmapInfo2]'."\n";
$pmb .= $imginfo[0]."\n";
$pmb .= $imginfo[1]."\n";
for( $x=0; $x<$imginfo[0]; $x++ )
{
$line = 0;
for( $y=0; $y<$imginfo[1]; $y++ )
{
$color = ImageColorAt($img, $x, $y);
$pos = ($imginfo[1]-$y-1);
$line = ($line | $color * pow(2,$pos));

}
$pmb .= $line."\n";

}

} else {
$pmb = 'Image isn\'t a PNG file or exceeds maximum size
(50x50 pixels).';

}
return $pmb;

}
else
{
return false;
}

}
else
{
return 'GD library not found. Unable to convert image.';
}

}

I could see where he was checking for the bitmap size, but I really didn't understand much else of it. I could have figured it out with time, but again, I didn't want to spend hours on this project! Luckily, the plain-English description of how the file format worked was more than enough for me to tackle this with Revolution. Without trying to translate any of the original PHP commands, here's the code I came up with:

on mouseUp

put the imagedata of the last image into iData
put the width of the last image into w
put the height of the last image into h

put "[BitmapInfo2]" & return & w & return & h & return into fld 1

repeat with column = 1 to w
put empty into theBinary
repeat with row = 1 to h
put (row-1) * w + column into thePixel
if charToNum ( char ( 4 * (thePixel - 1 ) + 2 ) of iData ) > 0 then
put 0 after theBinary
else
put 1 after theBinary
end if

end repeat

put baseconvert (theBinary,2,10) & return after fld 1

end repeat


end mouseUp

I don't know about you, but I find this a lot easier to understand! It took me about 20 minutes to figure it out. My first try had the pixels being reversed (black was white and vice versa), so after I fixed that, I actually had a totally functional conversion utility in no time flat.

I worked up this simple utility in far less time than it would have taken me to write a web-based tool, even though I already had the "hard part" written for me.

How I Did It

I never had to analyze the contents of a bitmap image before. So I looked up "image" in the online dictionary and discovered Revolution provides a very handy "imagedata" function which can look at any pixel in an image and return the color values for it. This was ideal for my purposes.

I made a new stack and added a scrolling text field and button to it. The text field would hold the PMB file data and the button was for my script.

Basically, I just work from the left to the right in the image. Each time I start a new column, I build up a binary representation of the bits that are black. Once I have that binary number, I use the handy "baseconvert" function to convert it to base 10 and tack it on to the end of the field.

The only complicated part of the script was the math to figure out what part of the image data to look at, because each pixel is represented by four bytes.

To use the script, I just import a graphic and click the button. The field instantly shows the PMB file data, which I simply copy and paste into a new text file, save with an extension of ".pmb" and load into the Polar uplink utility.

It would have been super-easy to have my script actually do the saving part on its own. In fact, I could have made the whole thing a tidy drag-and-drop utility where you could drop any bitmap image onto the stack and have the PMB file automatically created right beside it. But I wanted to spend as little time as possible on the task and, for this article, show as close a comparison to the original web utility as possible.

That is the great thing about Revolution. You spend so little time with the "hard parts" that it frees you up to add more functionality, better user interface, and other niceties. Or simply move on to other tasks.

It took less than 30 minutes for me to get this custom logo on to my exercise watch.

I'm sharing this story with you because it's an example of one of the best reasons to own Revolution. Even when you're not building the next "killer app" you can use Revolution to solve everyday tasks, making "quick and easy" more than just empty marketing-speak.

There are hundreds of times I've used Revolution and its flexible language to solve business problems that would take hours to handle with another tool. The little script I wrote is easy to understand if I come back to it later, even though I didn't add a single comment to it. (That's what "self-documenting code" is all about!)

I never thought I'd be in the business of converting graphic file formats, but Revolution came to my assistance and made the job a piece of cake! (Oh, better not mention cake!) Off to the gym!

 
©2005 Runtime Revolution Ltd, 15-19 York Place, Edinburgh, Scotland, UK, EH1 3EB.
Questions? Email info@runrev.com for answers.