Designing bitmapped graphics

User interfaces and games can be made much more interesting using color graphics. The GLCD library includes a function called GLCD_DrawBitmap() that can be used to render 16-bit color bitmaps. Bitmaps can be designed using standard editors or downloaded from elsewhere. The following recipe shows you how to generate a simple bitmapped representation of a ball that can be used with the helloBounce and helloPong recipes we developed in Chapter 2, C Language Programming. We'll call this recipe bitmapBounce_c6v0.

How to do it…

To design bitmapped graphics, follow these instructions:

  1. Create a color bitmap of width 16 pixels and height 24 pixels using the Windows Paint application. A screenshot of what this should look like is displayed, as follows:
    How to do it…
  2. Save the ball icon as a standard 24-bit bitmap, with the filename as ball.bmp.
  3. Use GIMP (http://www.gimp.org) to convert the 24-bit-per-pixel bitmap to a 16-bit-per-pixel format and store the pixel values in an array. First install GIMP and open the ball.bmp file.
    How to do it…
  4. Export the image as a C source file in 16-bit format using the GIMP export sub-menu. This creates the C source file (in this case, named ball_16bit.c).
    How to do it…
  5. Clone the folder named helloBounce_c2v0 from the Creating a game application – Stage 1 recipe that we introduced in Chapter 2, C Language Programming, and cut and paste the contents of the ball_16bit.c file into helloBounce.c, as follows:
    /* GIMP RGB C-Source image dump (ball_16bit.c) */
    static const struct {
    unsigned int    width;
    unsigned int    height;
    unsigned int    bytes_per_pixel; /* 2:RGB16 3:RGB 4:RGBA */ 
    unsigned char    pixel_data[16 * 24 * 2 + 1];
    } gimp_image = {
      16, 24, 2,
      "377377377377377377... etc.
    }
  6. Delete the extern GLCD_FONT GLCD_Font_16x24; declaration:
  7. Search for the following references:
    GLCD_Font_16x24.width 
    GLCD_Font_16x24.height

    Replace these reference with the following ones:

    gimp_image.width 
    gimp_image.height
  8. Delete the call to GLCD_SetFont (&GLCD_Font_16x24);.
  9. Search for the following statement:
    GLCD_DrawChar ( x, y, 0x81 );

    Replace this statement with the following one:

    GLCD_DrawBitmap ( x, y, gimp_image.width, gimp_image.height, gimp_image.pixel_data );
  10. Rebuild, download, and run the program.

How it works…

The ball used in the original recipes in Chapter 2, C Language Programming, is rendered using the filled circle character, which is one of a number of binary character bitmaps defined in a file named GLCD_Fonts.c. We're now using the GLCD_Bitmap() function to render the ball rather than GLCD_DrawChar(). This function expects a pointer to a 16-bpp bitmap. The bitmap data is provided by GIMP. The escape sequences 377377377, and so on, represent characters in the string encoded in octal. Therefore, 3778 = 111111112 and two bytes encode each 16-bit pixel, so 16-bit bitmaps can represent 65,536 colors. If the alpha channel is omitted (as in our case), then RGB channels are encoded by 5, 6, and 5-bits, respectively.

There's more…

The pixel data field of gimp_image comprises 16 x 24 x 2 + 1 = 769 bytes. If we store larger images in this way, our executable code image will quickly exceed the maximum allowed under the terms of our free MDK license. However, after examining the values in the array, we can see that many of the values are repeated, and this suggests that there may be a more efficient way of storing the pixel values. Run-length encoding (RLE) is a lossless compression algorithm that exploits the fact that there are often many repeated values in a bitmap (that is, adjacent pixels are often the same color). There are many variations of run length encoding, and a good introduction to the topic is given by Arturo Campos (http://www.arturocampos.com/ac_rle.html). We can export a run length encoded-version of our 16-bit BMP using GIMP.

There's more…

GIMP adopts a run length encoding format known as PackBits, which was originally developed by Apple. A data stream encoded by PackBits comprises a series of packets. Each packet consists of a one byte header followed by data. The header byte (n) is interpreted as a signed value (8-bit 2's complement) and the data. A positive value (n) indicates that the n data elements that follow should be interpreted as literal values, and a negative value implies that the single data element that follows should be repeated n times. The data structure (produced by GIMP) with run length encoded data representing the pixel values exported from the ball.bmp file is as follows:

/* GIMP RGB C-Source image dump 1-byte-run-length-encoded 
   (ball_16-bit_rle.c) */
static const struct {
unsigned int  width;
unsigned int  height;
unsigned int  bytes_per_pixel; /* 2:RGB16 3:RGB 4:RGBA */
unsigned char  rle_pixel_data[390 + 1];
  } gimp_image = {
    16, 24, 2,
    "3253773775377377... etc.
}

The run length encoded image comprises just 391 bytes (approximately 50% compression).To render the encoded bitmap, we'll need to define a version of GLCD_Bitmap() that unpacks the data before writing it to the GLCD:

int32_t GLCD_RLE_Bitmap (uint32_t x, uint32_t y, uint32_t width, uint32_t height, const uint8_t *bitmap) {
  
  int32_t npix = width * height;
  int32_t i=0, j;
  uint16_t *ptr_bmp;
  uint8_t count;
 
#if (GLCD_SWAP_XY == 0)
  y = (y + Scroll) % GLCD_HEIGHT;
#endif

  GLCD_SetWindow(x, y, width, height);

  wr_cmd(0x22);
  wr_dat_start();

  while (i<npix) {
    count = *bitmap++;
    ptr_bmp = (unsigned short *) bitmap;

    if (count >= 128) {
      count = count-128;
      for (j = 0; j<count; j++) { /* repeated pixels */
      wr_dat_only(*ptr_bmp);        
    }
    bitmap+=2; /* adjust the pointer */
  }
  else {
    for (j=0; j<count; j++) 
    wr_dat_only(ptr_bmp[j]);
    bitmap+=(count*2); /* adjust the pointer */    
  }
  i+=count;
  } /* while */

  wr_dat_stop();
  return 0;
}

As the library source file, GLCD_MCBSTM32F400.c, is read-only, we'll need to add the GLCD_RLE_Bitmap() function to a local copy (named GLCD_MCBSTM32F400_plus.c). We'll also need to add a local copy of Board_GLCD.h (Board_GLCD_plus.h) that includes the function prototype, GLCD_RLE_Bitmap(). Remember to modify the conditional preprocessor statement, as follows:

#ifndef __BOARD_GLCD_PLUS_H
#define __BOARD_GLCD_PLUS_H

Include a modified version of the header in rle_bounce.c and GLCD_MCBSTM32F400_plus.c. We've named this recipe that uses run length encoding rleBounce_c6v0.

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

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