Lesson 5 : More ByteImage


Lesson 4 : PNM Files | Lesson 6 : MPEG Basic | Contents


In this lesson, you will learn more about ByteImages, including masking and casting. A mask is representing by a BitImage. We first read in the file lenna.ppm and store them in three ByteImages r, g and b. If you don't understand the following code, you should go back to lesson 4 and read it again.

cd C:/Dali/doc/tutorial
package require DvmBasic
package require DvmByteGeom
package require DvmPnm

set size [file size lenna.ppm]
set bs [bitstream_new $size]
set bp [bitparser_new]  
bitparser_wrap $bp $bs
set file [open lenna.ppm r]
fconfigure $file -translation binary -buffersize 65536
bitstream_channel_read $bs $file 0
close $file
set hdr [pnm_hdr_new]
set len [pnm_hdr_parse $bp $hdr]
if {[pnm_hdr_get_type $hdr] != "ppm-bin"} {
        puts "input file is not a binary ppm."
}
set w [pnm_hdr_get_width $hdr]
set h [pnm_hdr_get_height $hdr]
set r [byte_new $w $h]
set g [byte_new $w $h]
set b [byte_new $w $h]
ppm_parse $bp $r $g $b

This time we are going to process a gray scale version of lenna. So we are going to convert the images into gray scale.

package require DvmColor
set lenna [byte_new $w $h]
rgb_to_y $r $g $b $lenna

Next we are going to read in a second PGM file, logo.pgm, which is the logo of DalÄ—.

set size [file size logo.pgm]
set logobs [bitstream_new $size]
set logobp [bitparser_new]  
bitparser_wrap $logobp $logobs
set file [open logo.pgm r]
fconfigure $file -translation binary -buffersize 65536
bitstream_channel_read $logobs $file 0
close $file
set hdr [pnm_hdr_new]
set len [pnm_hdr_parse $logobp $hdr]
if {[pnm_hdr_get_type $hdr] != "pgm-bin"} {
        puts "input file is not a binary pgm."
}
set w [pnm_hdr_get_width $hdr]
set h [pnm_hdr_get_height $hdr]

The above code read the logo image into the BitStream logobs. Now we should store the image into a ByteImage. DalÄ— provide the casting mecahnism to avoid memory copying.

set logo [bitstream_cast_to_byte $logobs $hdr $len]

What this do is that we treat the data in the BitStream, starting from location len as a PGM image according to the properties specified in hdr. logo and logobs shared the same memory and therefore we cannot free logobs just yet. logo should look like this :

Now what we want to do is to overlap the clock in logo over the face of lenna. We want pixels which are almost white in logo to be replaced by pixels from lenna. We can do so by using a mask.

set mask [bit_new $w $h]
bit_make_from_key $logo 245 255 $mask

This will create a mask with the same size as logo, with bit set to 1 at location where the pixel in logo has value range from 245 to 255. mask should look like this :

Now we simply copy the pixels from lenna into logo using mask to determine which pixel to copy.

byte_copy_with_mask $lenna $mask $logo

The result looks like this (uglier than I thought) :

Now we can output the result to a PGM file, starting with the header.

set file [open masked.pgm w]
fconfigure $file -translation binary -buffersize 65536
bitparser_seek $bp 0
pnm_hdr_set_type $hdr "pgm-bin"
pnm_hdr_encode $hdr $bp
bitstream_channel_write $bs $file 0

Writing the body is slightly tricky. Remember that logo share the same memory as logobs. So it is not neccessary that we copy or encode logo into another BitStream. We can output logobs to file directly. But it is WRONG to call :

bitstream_channel_write $logobs $file $len  # WRONG 

Recall what bitstream_channel_write do : it will write all bytes starting from len to the end of valid data in it to the output channel. But since we did not call write directly into logobs (we cast it to a ByteImage and modify the ByteImage), there are no valid data in logobs. So the correct way to write logobs is to explicitly specify how many bytes to write :

bitstream_channel_write_segment $logobs $file $len [expr [byte_get_width $logo]*[byte_get_height $logo]]
close $file

That should do it. Oh, remember to clean up by deallocating everything :

bitstream_free $bs
bitparser_free $bp
byte_free $r
byte_free $g
byte_free $b
byte_free $lenna
bitstream_free $logobs
bitparser_free $logobp
pnm_hdr_free $hdr
byte_free $logo
bit_free $mask

Source code for this lesson : l5.tcl


Lesson 4 : PNM Files | Lesson 6 : MPEG Basic | Contents


Last Updated : 06/03/2025 10:50:29