CS 0449 – Project 1: Mastermind and EXIF Viewer

CS 0449 – Project 1: Mastermind and EXIF Viewer

Due: Monday, February 12, 2024, by 11:59pm

Your first project is to write two programs in C that provide some experience with a wide range of the topics we have been discussing in class.

Mastermind Implementation (30 points)

In this game, the computer chooses 4 pegs each with one of 6 colors. This is the color-based predecessor to Wordle. The player’s job is then to guess the colors that the computer has chosen in the proper order. After each guess by the player, the computer will then give two numbers as feedback. The first number is how many pegs are the proper color and in the proper position. The second number is how many pegs are the proper color, but not in the correct position.

What you need to do:

 Generate a random computer guess of four colors out of:

o Red, Orange, Yellow, Green, Blue, Purple

 Read a guess from the user as a string of colors (see example below)

 Score the guess, and report the two values back to the user

 Allow the user to continue to guess until they get it correct, or reach 10 turns and they lose.

 Allow the user to play the game multiple times

Example:

Welcome to Mastermind!

Would you like to play? yes

Enter guess number 1: rrrr

Colors in the correct place: 1

Colors correct but in wrong position: 0

Enter guess number 2: rrgg

Hints

 Generating random numbers in C is a two-step part. First, we need to seed the random number generator once per program. The idiom to do this is:

srand((unsigned int)time(NULL));

 When we need random numbers, we can use the rand() function. It returns an unsigned integer between 0 and RAND_MAX. We can use modulus to reduce it to the range we need:

int value = rand() % (high - low + 1) + low;

EXIF Viewer (70 points)

An EXIF tag is embedded in many image files taken on a digital camera to add metadata about the camera and exposure. It is a complicated format, but we can simplify it to where we can write a simple viewer that will work with many JPEG files.

A JPEG file begins with the 2 byte sequence 0xFF, 0xD8. After that, a special JPEG marker (0xFF 0xE1) indicates an application specific segment, called APP1. We will assume (but you must verify) that there is no APP0 (0xFF 0xE0) section prior to APP1. This means the first 20 bytes of a JPEG with an EXIF tag will be:

Next, an array of TIFF (Tagged Image File Format) Tags will store the information we are looking for. At offset 20, we find a 2-byte (unsigned short) count that tells us how many tags there will be in this section.

A TIFF tag is 12 bytes that are defined as:

Loop through the file count times, reading a single TIFF tag at a time. We will only be concerned with 3 different tags in this section. Simply ignore any other tag that appears. The three tags we are concerned with have the 2-byte identifiers in the table below:

Let us take the first one as an example. We read in a 12-byte TIFF tag and find that its identifier field is 0x010F. Its data type field will be 2, which means that the data is encoded in an ASCII string. The number of data items field will tell us how many bytes our string has.

The final field in the tag can contain the value of the data itself if it fits in 4 bytes, or it can contain an offset to the data elsewhere in the file. Since an arbitrary string cannot fit in 4 bytes, in our case this value is an offset. It’s an offset from the beginning of the TIFF header, which occurred at byte 12 of the file. So we seek to 12 + offset in the file and read each letter from that position in the file, until we have read them all (we’ll encounter a NUL terminator at the end).

At this point, we’ve read the manufacturer string. We must seek back to the location in the file where we were reading tags and continue on to the next one.

To make this concrete, say we encounter our Manufacturer String tag while reading bytes 22-34 of our file. The tag would be:

The 6 tells us how many bytes the string will be (including the NUL terminator). The 158 tells us to seek to 158 + 12 bytes from the start of the file (the 12 bytes is the offset of the TIFF header from the start of the file).

When we seek to offset 170, we read in “Canon”, the manufacturer of the camera.

We must now seek back to offset 34 so that we can read the next tag in this section.

If we encounter the 0x8769 identifier, there is an additional Exif block elsewhere in the file. We can stop reading at this point even if we haven’t read all count tags because the TIFF format states that all identifiers must be in sorted order.

We will seek to the offset specified in this Exif sub block tag, again +12 bytes. There, we’ll repeat the above process one more time to get more specific information about the picture.

First, read in a new count as an unsigned short. Next, loop, reading more 12-byte TIFF tags from the file.

This time, we’ll be concerned with the following fields:

The good news is that type 4 means that the value is directly encoded in the last 4 bytes of our tag and no seeking needs to be done.

Type 5 requires us to behave like we did with the string, but rather than reading several single-byte characters, we will read 2 unsigned ints. Display the ratio of the two numbers as shown in the example below.

What To Do

For your project you will make a utility that can print the contents of an existing tag, if there.

Make a program called exifview and make it so that it runs with the following command line:

./exifview FILENAME

It should print the contents of the EXIF tag to the console if present, or give a message if not present or readable by our program.

Output

$ ./exifview img1.jpg

Manufacturer:      Canon

Model:                Canon EOS REBEL SL1

Exposure Time:    1/80 second

F-stop:                f/2.8

ISO:                    ISO 2000

Date Taken:          2013:08:20 22:23:45

Focal Length:        40 mm

Width:                  512 pixels

Height:                 768 pixels

Hints and Requirements

 We need to treat these files as binary files rather than text files. Make sure to open the file correctly, and to use fread for I/O.

 You must use a structure to represent a JPEG/TIFF/EXIF header and another struct to represent a TIFF tag. Do NOT use a bunch of disjoint variables. Do your fread() with the whole structure at once. (That is, read an entire tag in one file operation.)

 If the header field does not contain the Exif string in the right place, print an error message that the tag was not found. If the TIFF header contains MM instead of II, print an error message that we do not support the endianness.

Environment

Ensure that your program builds and runs on thoth.cs.pitt.edu as that will be where we are testing.

We have provided two sample jpg files with valid EXIF tags according to our limitations. Copy them to your working directory on thoth by using the command:

cp ~jmisurda/public/cs449/*.jpg .

The dot at the end is important as it represents the current directory in Linux.

Submission

When you’re done, create a gzipped tarball (as we did in the first lab) of your commented source files and compiled executables.

Copy your archive to the directory:

~jmisurda/submit/449/

Make sure you name the file with your username and -project1, and that you have your name in the comments of your source file. Please do NOT submit the sample picture files we provide.

Note that this directory is insert-only, you may not delete or modify your submissions once in the directory. If you’ve made a mistake before the deadline, resubmit with a number suffix like abc123-project1_1.tar.gz

The highest numbered file before the deadline will be the one that is graded, however for simplicity, please make sure you’ve done all the work and included all necessary files before you submit.

发表评论

电子邮件地址不会被公开。 必填项已用*标注