Chapter 5. Making a Jigsaw Puzzle Application

Picture this…

So far, we've been dealing with a lot of text or calling mobile OS features. These are neat things, but they're not that visual. If you were longing to mess around with pictures and image data, your time has come!

LiveCode isn't naturally a graphics powerhouse and its way of handling image data (often referred to as "bitmap data" by other tools) is somewhat unusual. It effectively stores the pixels of an image as a series of single byte characters to represent the red, green, and blue values of each pixel. Handling a final image is quite flexible, but in order to create something along the lines of a jigsaw puzzle, we need to understand the format of imageData, a LiveCode property.

In this chapter, we will:

  • Examine the way LiveCode stores bitmap data in an image object
  • Find a way to use a single bitmap in place of 50 buttons
  • Make a collision detection map
  • Create a jigsaw puzzle app that takes advantage of several mobile device features

Image data format

In other authoring tools, such as Adobe Director and Adobe Flash, bitmap data is stored as a matrix of 24-bit or 32-bit values. If you want to know the color of the 20th pixel from the left edge in the 15th row from the top of the image, you would have to use a getPixel function with these numbers filled in. In Flash, which uses a zero starting point for all its variable types, you would have to write the following code:

pixelcolor = bitmapvariable.getPixel(19,14);

You would in fact have to start this line with var pixelcolor:uint, but here we're looking at the main differences and not the oddities of having a strongly typed programming language! In Director, which like LiveCode uses 1 based variables, you would have to write the following code:

pixelcolor = imagevariable.getPixel(20,15)

Again, there's no need for variable typing or even a semicolon at the end of the line. While we digress, Flash too, doesn't need the semicolon at the end or at least, you don't have to type it yourself. Flash knew what you meant! Getting back to the point…

In LiveCode, each pixel of an image is represented by four bytes, which you can access as if they are single-byte characters. The range of values in a byte is 0-255, and storing such values, especially the value 0, in character variables does not work out well. Therefore, you would have to convert the character value into a numeric value before making use of it. The basic problem is that, although the numeric value is stored in a variable, when you come to do calculations on it, LiveCode wants to work in Base 10 arithmetic and not in the binary form inside the variable. You have to convert the variable into something that can be processed using the charToNum function.

Note

So, why would a character variable not like zeros you ask! Well, in the earliest days of personal computers, the predominant programming language was Pascal. In Pascal, a variable that contained a literal string needed a way to know how long the string was. The first byte of a Pascal string stores the length of the string, which was fine up to 255 characters, and in those days, it was most likely thought of as enough, and more than anyone would ever need! In real life though, strings can be longer than 255 characters. This paragraph alone is over 900 characters long. To solve this issue, the C programming language used a zero to indicate the end of a C String. You could have a million characters in a row; however, only the last one would be a zero. RGB values don't care about the limitations of C strings and there are zeros all over the place, which is why we convert it to a numeric value as soon as we can.

In addition to the oddity of each pixel being stored as four bytes of information, there's also no way to tell specify rows and columns. All the pixels in an image have their four bytes end to end; you have to do a calculation to know where in the data the pixel you're looking for is located. If you have worked on a bitmap editor before, say Photoshop or Gimp, you must be aware that you select content based on an X and Y co-ordinate value that correspond to the column and row that the pixel is located in. LiveCode doesn't let you access bitmaps in this way. Hence, we need to do a calculation.

Here's how the pixel from the preceding example would be retrieved in LiveCode if you want it as a 24-bit value:

put getPixel(""test image"",20,15) into pixelcolor

function getPixel pImage,pX,pY
  put the imageData of image pImage into tImageData
  put the width of image pImage into tWidth
  put ((pY-1)*tWidth + (pX-1)) * 4 into tStartChar
  put charToNum(char tStartChar+2 of tImageData) into tRed
  put charToNum(char tStartChar+3 of tImageData) into tGreen
  put charToNum(char tStartChar+4 of tImageData) into tBlue
  return tRed*65536+tGreen*256+tBlue
end getPixel

On the face of it, this is one of the few cases where the way it's done in LiveCode is considerably longer than in other languages. However, quite often, you really need the red, green, and blue values from the pixel, and in other languages, you have to take extra steps to extract these values.

The extra steps needed to make the returned number a 24-bit RGB value are no big deal, as LiveCode is easily extended by your own functions. If you need the 24-bit value, use the preceding function and you will have added a getPixel function to the LiveCode language. You still have to do the calculations to even get at just the red value. Maybe one day, LiveCode will have a built-in getPixel function that works quicker than your own function. The 24-bit number returned here is in fact represented as three decimal numbers and not as a 24-bit binary value, but it would still be generally referred to as 24 bit.

Mystery byte…

The first character of the four that represent one pixel is not used. LiveCode has tutorials on how to use imageData, where that byte is referred to as Alpha. That makes sense, as even the other tools that give you a 32-bit number have the value broken up into Alpha, Red, Green, and Blue. Why doesn't that byte, which RunRev calls Alpha, contain the alpha value? Who knows!

One possibility is that the value doesn't serve its purpose well enough. When talking about alpha transparency, you sometimes may mean that the image is transparent, as might be the case in a GIF image. Other times, you may mean that it's translucent, where it's only partially see-through.

To solve the ambiguous nature of the problem, LiveCode has two other properties of an image, maskData and alphaData:

put the maskData of image "test image" into tMaskData
put the alphaData of image "test image" into tAlphaData

These properties of an image still have all the rows end to end, and you have to do the calculation to find where a given pixel's alpha value is stored.

With maskData, you get a set of values for each of the pixels. For every value other than 0, the pixel is visible.

With alphaData, you get a set of values of the opaqueness of the pixel. 0 would be fully transparent, 255 would be fully opaque, and the values in between will be translucent. 128 would be 50 percent opaque.

Later in this chapter, we are going to make use of both maskData and alphaData, and we will refer to the 0-255 alphaData value as its transparency, and the zero or nonzero maskData value as its mask.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.23.101.60