oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Basics of Transparent Blitting, Part 2
Pages: 1, 2

The Blitting Procedure

To really make this useful let’s create a procedure that performs the transparent blit operation. We’re going to stuff all the code from above into this procedure so there is nothing new introduced here.

Remember from the previous example of writing, the hexadecimal conversion procedure that we passed some arguments into the procedure. Our blitting procedure is going to require some arguments to pass in to make it useful.

We'll need to know some information about the source image: it’s name, the top-left coordinates we want to blit from, and the width and height of the sprite to blit. We have:

src_image src_x src_y width height

We will need to know the destination image name and the top-left coordinate of the bounding rectangle to blit to. Here we have:

dst_image dst_x dst_y

And won’t we need to know what the value of the transparency pixel is? We will need,


This should be enough for us to define the procedure. It looks like:

proc transparent_blit { trans_pixel \
  src_image src_x src_y width height \
  dst_image dst_x dst_y } {

  procedure body

Cutting and pasting all the code snippets in for our procedure, it looks like this:

  # transparent_blit
  # ----------------
  # Performs a transparent blit operation.
  # Arguments:
  # trans_pixel - transparent pixel value
  # src_image - source image to be copied
  # src_x - x start of source rectangle
  # src_y - y start of source rectangle
  # width - width of rectangle
  # height - height of rectangle 
  # src_mask - hex value for transparency pixel
  # dst_image - destination image
  # dst_x - x start of destination rectangle
  # dst_y - y start of destination rectangle
  # Returns:
  # none
  proc transparent_blit { trans_pixel \
  src_image src_x src_y width height \
  dst_image dst_x dst_y } {
  # calculate source bounding rectangle 
  set src_x2 [expr $src_x + $width]
  set src_y2 [expr $src_y + $height]
# calculate destination bounding rectangle
  set dst_x2 [expr $dst_x + $width]
  set dst_y2 [expr $dst_y + $height]
# get source image raw data
  set raw_src_data \
  [$src_image data -from $src_x $src_y $src_x2 $src_y2]
# get destination image raw data
  set raw_dst_data \
  [$dst_image data -from $dst_x $dst_y $dst_x2 $dst_y2]
  # set src_scan_row
  # set dst_scan_row
# raw_image_data is the target buffer
  set raw_image_data ""
for {set scan_row_index 0} {$scan_row_index < $height} \
  {incr scan_row_index} {
  set src_scan_row [lindex $raw_src_data $scan_row_index]
  set dst_scan_row [lindex $raw_dst_data $scan_row_index]
  # reset raw_scan_row data for a new scan row
  set raw_scan_row ""
  for {set pixel_index 0} {$pixel_index < $width} \
  {incr pixel_index} {
  set src_pixel [lindex $src_scan_row $pixel_index]
  set dst_pixel [lindex $dst_scan_row $pixel_index]
  # check if source pixel is transparent pixel
  if {$src_pixel == $trans_pixel} {
  # write the destination pixel
  set raw_scan_row "$raw_scan_row $dst_pixel"
  } else {
  # write the source pixel
  set raw_scan_row "$raw_scan_row $src_pixel"
  # END for each pixel 
  puts $raw_scan_row 
  lappend raw_image_data $raw_scan_row
  # END for each scan row
  # copy the new image to the buffer

  # create the Tk temp image buffer
  set temp_image \
  [image create \
  photo -height $height -width $width -format gif]

# copy the raw blit data over to the Tk temp image
  $temp_image put $raw_image_data -to 0 0
# copy the Tk temp image to the destination buffer 
  $dst_image copy $temp_image -from 0 0 $width $height \
  -to $dst_x $dst_y $dst_x2 $dst_y2
# RGB_convert_decimal_hexadecimal
  # ------------------------------
  # Convert image pixel values from decimal to hexadecimal
  # Arguments:
  # transparency_pixel - Tcl list RGB values from 
  # Tk image library.
  # Returns:
  # hexadecimal string -formatted RGB values for 
  # Tk image data analysis.
  proc RGB_convert_decimal_hexadecimal { transparency_pixel } {
  # convert to hexadecimal
  set R_value \
  [format "%02x" [lindex $transparency_pixel 0]]
  set G_value \
  [format "%02x" [lindex $transparency_pixel 1]]
  set B_value \
  [format "%02x" [lindex $transparency_pixel 2]]
  # create the transparency value string
  set RGB_value "#$R_value$G_value$B_value"

  return $RGB_value
  # load the art file
  set filename "/game_dev/game_art.gif"
  set sprites [image create photo -file $filename]

# load the raw pixel data into raw_monster_data
  set raw_monster_data [$sprites data -from 265 737 328 800]
set RGB_decimal_pixel [$sprites get 265 737]
  set transparent_pixel [RGB_convert_decimal_hexadecimal \
# create the offscreen buffer
  set video_game_width 640
  set video_game_height 480
# create a blank offscreen image
  set offscreen [image create photo \
  -height $video_game_height -width $video_game_width]
# copy the background mountains image
  $offscreen copy $sprites -from 0 0 639 479 -to 0 0 639 479

transparent_blit $transparent_pixel \
  $sprites 265 737 63 63 $offscreen 320 303
# create the canvas
  canvas .canv -width 640 -height 480 -background black 
  pack .canv -side top -expand yes -fill both
  .canv itemconfigure $offscreen -image $offscreen
  .canv create image 0 0 -image $offscreen -anchor nw
Figure 5. Voila! The animated cell frame.


Now isn’t that more like it? You can create video-game sprite animation just as you see on your Game Boy Advance SP. Tired of playing with those old pocket-monster sprites? Go and make your own game. Play around with the animation cells I provided. You're definitely going to have to go get an art application.

Adobe Photoshop is nice, put nice comes at a hefty price. The next best solution is MacGIMP, which will cost you around $30. So go forth and design that one video game that will change the world!

Michael J. Norton is a software engineer at Cisco Systems.

Return to