CPSC120A
Fundamentals of Computer Science I

Lab 26

File I/O

Use the command line to create a new directory called lab26 in your labs directory. Make sure all of the .py files that you create for this activity are in that directory.

Steganography

Cryptography can be used to make the contents of a message secret, but sometimes you want to hide that a message is even being sent. Steganography is one way to hide messages, and a common technique takes advantage of our inability to perceive small changes in colors. For example the image below consists of two boxes with different colors.

The left box has the RGB values (161, 187, 150). The box on the right has the RGB values (162, 188, 151). The two boxes appear to be the same color because the RGB values are similar. A message can be hidden in an image by making small changes to the RGB values of an existing image.

A common way of modifying an image is to change only the least significant bits of the RGB values. The least significant bit of a number is the right-most bit and represents the value 20, or 1. Therefore, the most a color value will change if the least significant bit is change is 1, which the above image demonstrates as imperceptible. The following whale image, for example, has a message encoded in it.

Details

Create a function called decode_image(ppm_file_name) in a file called steganography.py. The program should return the secret message that is embedded in the specified image file. The message is encoded as 8-bit ASCII in the least significant bit of the image's color data. Assume that the number of color values in the file is a factor of 8. Once you have tested your program on a simple example, you can test it on the above whale image.

Some things to keep in mind:

Example

>>> image_file = open("demo.ppm", "r")
>>> print(image_file.read())
P3
1 8
255
122
101
215
42
2
128
200
13
64
203
155
130
36
172
91
180
88
77
55
22
44
66
33
99
>>> print(decode_image("demo.ppm"))
abc

Hint

  • You are going to use the accumulator pattern here for strings, adding the least significant bit of the color values. A number that is odd has a 1 as the least significant bit, a number that is even has a 0 as the least significant bit.

  • You can convert a binary string to a base-10 integer by using the built-in int function.

  • You can convert an integer to a character using the built-in chr function.

 

Challenge

Write a function that can embed messages into images. The function should take three parameters: a message, an input image file name, and an output image file name. It should read in the input image, modify the least significant bits of the color values to embed the message, and write the new image to the specified output file.

Database

Many of the programs that you use on a daily basis all have some element of persistence to them. For example, Emacs can read and write text files that the user writes, or the Messages list on your phone keeps track of all the text-messages you have received. In fact, these programs would be worthless if they couldn't store this data.

Even programs that you wouldn't typically think of require a large amount of stored data in order to accomplish their tasks. Mozilla Firefox, for example, creates an entire directory to store the files necessary to store the information that persists between browsing sessions. It is located in a hidden folder in your home directory called .mozilla/.

In fact, if you have ever get an error opening Firefox because it claims there is already a browser instance open, you can solve the problem by removing one of these persistent files:

$ cd ~/.mozilla/firefox/<some random string of characters>.default/
$ rm lock .parentlock

Since (seemingly) all useful programs rely on files, today you will write such a program. Your program will allow the user to write and store some information using your program. The choice is up to you, but here are some ideas:

Details

Create a program called database.py. This program will allow the user to enter in their information, and have it saved for later. This exercise is pretty open ended, but there are a few restrictions:

Example

$ python3 database.py
Please enter the file you wish to load from and save to: cd_db.txt
Welcome to the CD collection processor!

Enter Album Title: The Wall
Enter Album Artist: Pink Floyd

**************Database**************
The Wall - Pink Floyd
************************************

Add more? Y

Enter Album Title: Physical Graffiti
Enter Album Artist: Led Zeppelin

**************Database**************
The Wall - Pink Floyd
Physical Graffiti - Led Zeppelin
************************************

Add more? N
$cat cd_db.txt
The Wall - Pink Floyd
Physical Graffiti - Led Zeppelin

Hint

Create two functions: add_entry(database_file_name, new_entry) and read_entries(database_file_name).

  • The read_entries should print the current contents of the database file.

  • The add_entry function should read the database file into a list, append the new entry to the end the list, and write the updated list back to the file.

Don't forget to close your file objects when you are done with them!

 

Challenge

It is possible to append to a file without having to first re-write the current contents. Take a look at the documentation for the open function, and see if you can figure out the mode necessary to accomplish this.

Submission

Please show your source code and run your programs for the instructor or lab assistant. Only a programs that have perfect style and flawless functionality will be accepted as complete.