Assignment 2: Color Models
Due to CMS by Sunday, March 8th at 11:59 pm.
Your second and last assignment will build upon the skills from the first one.
You will still write functions and test them. But this time your functions
will be part of a larger piece of software. A lot of people think of Python
as a language for processing text and data. This assignment shows that Python
can be used for graphical applications as well.
One of the main things that you will learn in this assignment is that there are many
different ways to represent color, and the choice of color model often depends on the
application. For example, RGB is used when the colors need to be displayed on a computer
monitor (such as a web site), while CMYK is often used for printing out colors on paper.
You have a bit longer to do this assignment than the previous one. It is due after
Fall Break, when the course is official over. With that said, you should still start
early on this assignment. If you do not know where to start, or if you are completely
lost, please see someone immediately: either
the instructor, or a consultant.
A little in-person help can do wonders.
As before, remember to fill out the survey
telling us how long you worked on this assignment.
Important:
Python has a built-in color conversion module called colorsys .
You are forbidden from using that module in this assignment.
Learning Objectives
This assignment is design to help you understand the following concepts.
-
It introduces three color models that are used in computing and graphics.
-
It gives you practice in writing complex functions with conditionals.
-
It gives you practice in writing functions with for-loops and data files.
-
It gives you experience with using traces debug program flow.
-
It introduces you to the notion of attribute invariants.
-
It demonstrates a complex Python application that spans multiple modules.
Even though this is a complex Python application, we have provided most of
the modules for you. You only need to focus on one module: a2.py
(as well as the unit test a2test.py )
Table of Contents
Authors: D. Gries, W. White, L. Lee, S. Marschner.
Academic Integrity and Collaboration
Academic Integrity
This assignment is a slightly modified version of an assignment given in a
previous semester. Please do this assignment without consulting (or seeking)
previous solutions. Consulting any prior solution is a violation of
CS1133's academic integrity policies.
Unlike the previous assignments, it is highly unlikely that your code for this assignment
will look exactly like someone else's. This is the first assignment that we will
actively be using Moss to check for instances of plagiarism.
We also ask that you do not enable violations of academic policy. Do not post your code
to Pastebin, GitHub, or any other publicly accessible site.
Important:
Python has a built-in color conversion module called colorsys .
You are forbidden from using that module in this assignment.
Collaboration Policy
You may do this assignment with one other person. If you are going to work
together, then form your group on CMS as soon as possible. If you do this
assignment with another person, you must work together. It is against the
rules for one person to do some programming on this assignment without the
other person sitting nearby and helping.
With the exception of your CMS-registered partner, we ask that you do not look at anyone
else's code or show your code to anyone else (except a CS1110 staff member) in any form
whatsoever. This includes posting your code on Piazza to ask for help.
It is okay to post error messages on Piazza, but not code. If we need to see your code,
we will ask for it.
An Overview of Color Models
Color Model RGB
The RGB system is named after the initials of the three color names:
red, green, and
blue. In this color model, light from these three colors is
mixed to produce other colors, as shown in the image to the left. Black is the absence of color;
white the maximum presence of all three.
In the upper right is a colored image. Below it is its separation into red, green, and blue (here
is a high resolution version).
In the three separation panels, the closer to black a point is, the less of that color it has.
For example, the white snow is made up of a large amount of all three colors, whereas the brown
barn is made up of red and green with very little blue. Because it works by adding colors to black,
the RGB system is “additive”.
The color model RGB is used in your TV and computer screens, and hence on web pages. Its roots are
in the 1953 RCA color-TV standards. But the idea has been around longer; see
this exhibit for some amazing full-color images
taken with an RGB camera over 100 years ago.
In the RGB model used in most systems, the amount of each of red (R), green (G) and blue (B)
is represented by a number in the range 0..255. Black, the absence of color, is [0, 0, 0];
white, the maximum presence of R, G, and B, is [255, 255, 255]. This means that there are
16,777,216 different colors.
In some graphics systems, RGB is used with float numbers in the range 0.0..1.0
instead of int values 0..255. The reasons for this discrepancy is that the mathematical formulas
for color require real numbers 0.0..1.0, but it takes a lot less memory to store ints instead
(and images require a lot of memory). In your program, you may have to convert each number in
the integer range 0..255 to a float in 0.0..1.0, calculate a mathematical
formula, and then convert back to 0..255.
Color Model CMYK
For your ink-jet printer, you buy expensive ink cartridges in the colors
cyan, magenta,
yellow, and black. The printer mixes these inks
in different amounts on paper to make the full range of colors.
Black is referred to using K (originally for “Key”) to avoid confusion with
Blue.
The process works similarly to RGB on a monitor, but in reverse. The paper starts off white
(equal parts red, green, and blue), and the colors of these inks are chosen so that cyan ink
absorbs red light, removing it from the color of the paper; similarly, magenta removes green,
and yellow removes blue. Black ink removes all three colors in equal amounts. For instance,
paper printed with only yellow ink appears the same color as a monitor that is displaying a
yellow color [255, 255, 0] because it has removed all the blue, leaving the red and green.
Printing magenta and cyan removes red and yellow and results in blue [0, 0, 255]. Because it
works by removing color, this kind of system is “subtractive”.
Theoretically, only C, M, and Y are needed to achieve any color, but in practice it is hard
to get a good black by mixing colored inks; instead you get a soggy, expensive brown-black.
By using the black ink to do the “heavy lifting” of absorbing most of the light
when printing dark colors, a lot of ink can be saved
(This is a simplified view of color printing; more complicated calculations are needed to get
accurate colors with real inks).
To demonstrate, in the upper right, we show you an image; below it is its separation
into cyan, magenta, and yellow. To the right of that, you see the same image separated
into four components; C, M, Y, K. Much less of the CMY colors is needed to make the image
when black is also used (here is an enlarged version of the
CMY image and an enlarged CMYK image).
In the CMYK system, each of the four components is traditionally represented by a percentage,
which we represent in our system as a float value in the range 0.0..100.0.
Color Model HSV (or HSB)
The HSV model, used heavily in graphics applications, was created in 1978 by Alvy Ray Smith.
Artists prefer the HSV model over others because of its similarities to the way humans perceive
color. HSV can be explained in terms of the cone that appears to the left.
H, the Hue, defines the basic color. H is an angle in the range 0 ≤ H < 360,
if one views the top of the cone as a disk. Red is at angle 0. As the angle increases, the hue
changes to orange, yellow, green, cyan, blue, violet, magenta, and back to red. The
image above shows the angles for some colors.
S, in the range 0 ≤ S ≤ 1, is the Saturation. It indicates the distance
from the center of the disk. The lower the S value, the more faded and grayer the color. The
higher the S value, the stronger and more vibrant the color.
V, the Value, also called the Brightness, is in the range 0 ≤ V ≤ 1.
It indicates the distance along the line from the point of the cone to the disk at the top. If
V is 0, the color is black; if 1, the color is as bright as possible.
To the right at the top is a picture. Below it we see its hue, saturation (white is zero
saturation, red is full saturation), and brightness components. The hue component shows color.
The snow has color, but its saturation is low, making it almost grayish. Look at the various
components of the image —the sky, the green grass, the snow, the dark side of the barn, and
so on — to see how each component H, S, and V contributes. You can see more detail in this
high-resolution version.
The introcs Color Classes
All of the color models of the previous section are provided by the module
introcs , which was installed with Cornell Extensions. This module
provides three different classes: RGB , CMYK , and
HSV . It lacks the ability to convert between these classes.
That is the focus of this assignment.
In addition to these three clases, introcs also has some constants
(e.g. global variables that should not be altered) that you can use for the various
colors. All of these colors are in the RGB color space.
For example,
introcs.MAGENTA is [255, 0 , 255] and
introcs.ORANGE is [255, 200, 0]. There is a
Wikipedia page with a
list of colors that gives
(non-Python) names to many RGB colors.
The Class RGB
The class RGB is the type of objects that represent RGB color.
Objects of type RGB have three attributes: red ,
green , and blue (they also have a secret attribute
alpha which will not be used in this assignment). For example,
if c is a variable containing a (name of) an RGB object, you
would use the expression c.red to access the red value.
The RGB constructor function takes three arguments, assigning
these values to the attributes in the order red ,
green , and blue . For example, to create an
RGB object representing the color red, use the assignment
red = introcs.RGB(255,0,0)
The Class CMYK
The class CMYK is the type of objects that represent CMYK color.
Objects of type CMYK have four attributes: cyan ,
magenta , yellow , and black . For example,
if c is a variable containing a (name of) a CMYK object, you
would use the expression c.cyan to access the cyan value.
The CMYK constructor function takes four arguments, assigning
these values to the attributes in the order cyan , magenta ,
yellow , and black . For example, to create a
CMYK object representing the color red, use the assignment
red = introcs.CMYK(0.0,100.0,100.0,0.0)
The Class HSV
The class HSV is the type of objects that represent HSV color.
Objects of type HSV have three attributes: hue ,
saturation , and value . For example,
if c is a variable containing a (name of) a HSV object, you
would use the expression c.hue to access the hue value.
The HSV constructor function takes three arguments, assigning
these values to the attributes in the order hue , saturation ,
and value . For example, to create an HSV object
representing the color red, use the assignment
red = introcs.HSV(0.0,1.0,1.0)
Attribute Invariants
All of the objects in this assignment have attribute invariants. An
attribute invariant is a property of an attribute (which is essentially a variable)
inside an object. The invariant cannot be violated. Attempting to violate an
invariant will cause an error and crash Python.
For example, for RGB objects, the red attribute has an invariant
that it must be an int and it must be in the range 0..255, inclusive. The
following code produces an error:
>>> import introcs
>>> rgb = introcs.RGB(255,255,255)
>>> rgb.red = -1
Traceback (most recent call last):
...
AssertionError: value -1 is outside of range [0,255]
The invariants in the introcs color classes are provided for your benefit. They are there
to help you catch errors. All you need to do is to make sure that you never assign a
value to an attribute that violates an invariant.
The invariants for this assignment are as follows:
-
All attributes of
RGB must be ints, and in the range 0 to 255, inclusive.
-
All attributes of
CMYK must be floats, and in the range 0.0 to 100.0, inclusive.
-
The
hue attribute of HSV must be a float in the range 0.0 to 360.0,
not including 360.0.
-
The
saturation and value attributes of HSV must all be
floats, and in the range 0.0 to 1.0, inclusive.
For more details see the color model documentation for this
assignment.
Colorblind Perception
In “Designing for the
color-challenged: A challenge”, Thomas Wolfmaier (1999) writes that “About 8% of (Caucasian)
males1 and 0.5% of females exhibit some form of color vision deficiency.
This includes your constructor, who has a mild form of deuteranomaly.
However, color is a major part of user interface design. Color is a very quick way to
impart lots of information. But if you ignore color blindness issues, you are potentially
causing problems for 1 out of every 20 customers. In your instructor's case, bad color
design made the game
Clash of Heroes
almost completely unplayable.
Colorblindness even has profound effects on users that are not colorblind:
Colors don’t matter much to [Mark] Zuckerberg; a few years ago, he took an online test
and realized that he was red-green color-blind. Blue is Facebook’s dominant color,
because, as he said, “blue is the richest color for me — I can see all of blue.”
— “The Face of Facebook”, Jose Antonio Vargas, The New Yorker, Sept. 20, 2010.
In this assignment, you will be working with an application that gives you an understanding
of how colorblind people see color. In the assignment, there is a folder colorblind
that has several files with 3x3 matrices. These matrices, when applied to a color value,
transform it into a new color value that approximate the vision of a colorblind person.
The image below, from Wolfmaier (1999), demonstrates the results of such transformations.
The top bar, labeled "Normal", shows the "rainbow" red-to-violet spectrum. Each point in the
subsequent bars shows what the color above it in the "Normal" space appears like for the corresponding
condition. For example, for someone with protanopia, a form of red-green color blindness,
the image shows that red comes out as a muddy yellow, and green comes out as a yellow as well.
Assignment Overview
For this assignment, we are providing you with a lot of code already written. In that
respect, this assignment is going to be a lot more like a lab, where you fill in the
extra details. In addition, we are providing you with an online
color conversion tool,
so that you know what your answers should look like.
Assignment Source Code
As we said above, this assignment will involve several files. You will need to download
five files. Three are completed by us, and the other two have functions stubs
or incomplete implementations that you must finish yourselves. They must all be in
the same directory for this assignment to work. You can find all of these
modules in a single compressed zip file, which is available here.
The following are the two completed source code files (You should not need to modify
the contents of any of these files at all):
a2app.py
-
This module provides the GUI functionality (e.g. window, sliders, and text boxes) of the program.
It will not work at first, but will become more functional as you complete more of the assignment.
colormodel.kv
-
This is not a Python module; this is a special file that Kivy uses to arrange the sliders,
buttons, and other widgets in the application. It must be in the same directory as all
of the other modules.
In addition, the following source code files are skeletons (i.e., they are incomplete and
you are expected to add functionality to them):
a2.py
-
The class contains the functions that do most of the work behind the scenes. Filling in the
function stubs in this class will help
a2app.py work properly.
a2test.py
-
This is a unit test module to verify that the module
a2 is working properly.
We do not trust our visual color perception enough to leave all the testing to "eye-balling".
It is incomplete; you are expected to add tests where directed.
In addition, there is also a folder called colorblind. This
folder contains several files ending in the suffix .dat. These files contain the
transformation matrices representing different types of colorblindness.
To get started with the source code, put them all in a new directory. They must all be
in the same folder to work. You then need to run a2app.py as a script.
That is, open the command shell and navigate to the directory for this assignment. Then type
python a2app.py
You will see a bunch of crazy messages that look like this:
[INFO ] Kivy v1.7.2
[INFO ] [Logger ] Record log in ...
[INFO ] [Factory ] 144 symbols loaded
[DEBUG ] [Cache ] register <kv.lang> with limit=None, timeout=Nones
[DEBUG ] [Cache ] register <kv.image> with limit=None, timeout=60s
[DEBUG ] [Cache ] register <kv.atlas> with limit=None, timeout=Nones
[DEBUG ] [Cache ] register <kv.texture> with limit=1000, timeout=60s
[DEBUG ] [Cache ] register <kv.shader> with limit=1000, timeout=60s
...
That is Kivy (our GUI library) initializing the application.
When the messages are done, you should see a GUI window that looks like the following.
In this application there is a solid color panel in the upper left, some sliders on
the right, and some text boxes and buttons down at the bottom. Right now, very little
works. If you move the RGB sliders, you will see the color panels change color; however,
none of the other sliders work. You can also change the color by entering the new color
value into the R, G, and B fields and then hitting the RGB button; none of the other
fields or buttons do anything.
Your job is to write and test, one by one, the functions in module
a2 . As you do, more and more of the GUI will work properly.
Understanding the Program GUI
A working GUI should look like the one shown below. There are two color panels on
the left. The first panel displays the current color. It contains text, displayed
in the complement color. This text displays the color values, in RGB, CMYK, and HSV,
for the background color.
The second panel contains a drop-down menu in the upper right. This drop-down menu
allows you to select a type of colorvision. If you select any value other than
"Normal", it will transform the color to simulate that version of colorblindness.
You can change the colors by moving the sliders. If you move the sliders in
one color model, then the sliders in the other color models will follow automatically.
This way, all three models (RGB, CMYK, and HSV) register the same color.
On the bottom, you will see fields into which you can type numbers for the RGB, CMYK, and
HSV components. In the illustration above, you can see that we have started to type
numbers into the fields for RGB. Once we are done typing, we can press the RGB button
to make this the new color. The same thing works in the other color models. This allows
you to try exact colors while testing your application.
The numbers in the text field should be in their respective ranges: 0..255 for R, G, B;
0.0..100.0 for C, M, Y, K; 0.0..1.0 for S, V; and 0.0..359.99999999 for H. If you type
in a negative number, the program replaces it and uses 0 instead. If you type in too large
a number, the program replaces it and uses the maximum value for the range.
We will show off our solution several times in class. We will also make it available
to TAs to show in office hours.
Experimenting with the Color Models
If we could, we would give you a sample solution to play with so that you would see
what a working program is supposed to look like. Unfortunately, we cannot do that.
Python is not a compiled language, so there is no easy way to give you a solution
without showing you the source code.
Click on Image to Experiment
Instead, we are doing the next best thing. We have provided you with an online color
converter. Click on the image above to go to a special web page where you can enter
various color values. This web page shows you what the answers should look like for
various inputs (after you enter a value in a field on that page, you have to click
on a different field to get the whole page to update to the new values).
Use this page to help you design your test cases for the rest of the assignment.
Testing and Debugging
You should use the testing and debugging methodologies that you used in
the first assignment.
You will want to unit test with a2test.py ; we have already
started several of the test procedures for you. You will be graded on the
completeness of your test cases. Remember our comments from the first
assignment.
You will probably want to add print statements to a2.py for
watches (e.g. print statements that display the contents of a variable) and
traces (e.g. print statements that indicate the line of code that is currently
executing). Traces will be particularly valuable for this assignment because
it is the first major assignment involving conditionals.
Because this is a much more complex assignment than the first, we recommend that you be
very descriptive with your watches and traces. Suppose you are trying to find an error in
function rgb_to_hsv (or in a function that calls rgb_to_hsv )
and that rgb_to_hsv changes a variable h at line 36.
Then, you might insert at line 37 a statement like
print 'rgb_to_hsv: h at line 36 is '+ str(h)
Assignment Instructions
Below, we outline the functions that you are expected to write for this assignment.
You should write and test your functions, one at a time, in the order given.
Read the text below, but also make sure you carefully read the specifications and
comments in the provided code. In this assignment, sometimes we give hints in the
specs/comments about how best to write your functions.
complement_rgb(rgb)
We gave you some partial code that you need to fix. The complement of a color is like
a color negative. If R, G, and B were color components of the RGB value in the range
0.0..1.0 (not 0..255!), then the color components of the complement would be 1-R, 1-G,
and 1-B. However, since we are using values in the range 0..255, the complementary
color of the RGB color [r, g, b] is the color [255-r, 255-g, 255-b].
Currently this function does not work. Instead, it makes a copy of the RGB object
in the parameter variable. You will need to change the arguments to the
RGB constructor to get it to return the complement
instead.
After completing this function, run a2app.py as a script. You will now
see text in the colored boxes. This text will have a lot of information, including
the RGB value of the current color. However, the CMYK and HSV information will
still be blank. In addition, the drop-down menu will still not work properly.
round(value, places)
This function might seem really weird. There is already a round function
built into Python. Why are we defining our own round function. The problem
is that built-in round in Python is underspecified;
the specification does not tell us how to accurately handle numbers on the border.
Depending on your computer, you might see the following behavior:
>>> round(100.55,1)
100.5
>>> round(100.45,1)
100.5
Most students find this really confusing, and it can make testing this assignment very
difficult. We are going to solve this problem by defining our own version of round.
This version will always round up numbers at the border. So round(100.55,1)
should return 100.6.
Currently this there is a stubbed-in return statement so that the function produces a
value of the right type (i.e., a float). Write this function, commented hints in the
function body. You should pay careful attention to the precondition, as that might
be helpful. We have also provided test cases for this function in the module
a2test (should you add more?) so that you can test it when done.
Throughout this assignment, you should use this version of round instead of
the built-in one. However, read the specifications of the other functions carefully.
Sometimes we do not want you to round at all. Only round when you are explicitly
told that you are allowed to do so.
str5(value)
This function is similar to round, except for two major differences. First
of all, it returns a string, not a number. More importantly, the number of places
to round to are not constant. For example, str5(1.0567) returns '1.057',
while str5(10.567) returns '10.57'
Within this assignment, this function should only be used to give
the GUI in a consistent format; values should always be 5 characters long. In particular,
it is meant to be used in the str5_cmyk and
str5_hsv functions below.
This function is also useful in testing, as shown in a2test . However,
it is not meant to be used in any other function. In particular, do not use
it in the conversion functions,
since that results in a loss of mathematical precision.
To implement this function, you will want to use the round function that
you defined in the previous step. Again, you should pay careful attention to the
precondition, as that might be helpful. We provided test cases for it in
module a2test (should you add more?).
Formatting CMYK and HSV Objects
To turn a color object into a string, you can use the str() function
which you have seen in class. This is fine for RGB objects, as the attributes
are integers. However, CMYK and HSV objects have float attributes, and they are
a lot messier. Floats could potentially have 18 digits!
The functions str5_cmyk and
str5_hsv act just like str() ,
except that they use str5 to limit the float attributes to
just 5 characters. The following example in the Python interactive shell
demonstrates the differences between these functions:
>>> import introcs
>>> color = introcs.HSV(12,0.46792,0.32456)
>>> str(color)
'(12.0,0.46792,0.32456)'
>>> str5_hsv(color)
'(12.00, 0.468, 0.325)'
str5_cmyk(cmyk)
Implement this function according to the specification in a2.py .
This function should call function str5 to round each CMYK value
to 5 characters. We have provided you with a test case in a2test.py
to show you how to test this funciton. You should provide at least one more
test.
str5_hsv(hsv)
Implement this function according to the specification in a2.py .
This function should call function str5 to round each HSV
value to 5 characters. We do not provide test cases for this function.
You must write at least two of them.
rgb_to_cmyk(rgb)
This function converts an RGB value to a CMYK value. When you get it working, moving the
RGB sliders will cause the CMYK sliders to move as well. However, the reverse is not true;
moving the CMYK sliders will still not affect the RGB sliders.
There will also be no affect to the HSV sliders.
There are several different ways to convert, depending on how much black is used in the
CMYK model. Our conversion uses as much black as possible.
Let R, G, and B be the color components of the RGB value in the range 0.0..1.0 (not 0..255!); that
means that you will need to divide the values in the RGB object by 255.0. Once you do that,
then the conversion is as follows:
-
Compute C' = 1 - R, M' = 1 - G, and Y' = 1 - B.
-
If C', M', and Y' are all 1, use the CMYK value (0, 0, 0 , 1).
If not, compute and use the following:
-
K = minimum of C', M', and Y',
-
C = (C' - K)/(1 - K), M = (M' - K)/(1 - K), Y = (Y' - K)/(1 - K).
The resulting CMYK values are in the range 0.0..1.0, and they must be converted to the
range 0..100.0. And that is it! Not too bad, right?
Do not round your answers. That is an unacceptable loss of precision.
When you implement this function, the numerical CMYK color will display
properly in the two color panes (assuming that str5_cmyk is
implemented correctly).
Testing
Providing test cases is a bit problematic because float
values are only approximations to the real values, and slightly different ways of
computing might produce different results. In fact, we saw this problem with currencies
in the
first assignment.
This time, instead of using assert_floats_equal , you are allowed to use
the str5 function defined in this assignment, since that is what appears
in the color panes of the GUI.
To show you how to do this, we have provided three test cases in a2test .
Add a few more test cases following our example. In designing your test cases,
remember that you can use the
online color conversion tool in order to find out what
the values in one color model should be in a different color model.
cmyk_to_rgb(cmyk)
This function converts a CMYK value to an RGB value. Once you get it working,
moving the CMYK sliders will cause the RGB sliders to also move (and so the two
sets of sliders will work in tandem).
Let C, M, Y, and K be the color components of the CMYK value, all in the range 0.0..1.0
(not 0..100.0; you will need to convert this first).
Then the conversion is as follows:
R = (1 - C)(1 - K),
G = (1 - M)(1 - K),
and B = (1 - Y)(1 - K)
This produces RGB values in the range 0.0..1.0, and they must be converted to the range
0..255. You should use rounding in converting the answer to an int. We will say it
again because students have not complied in previous semesters: ROUND; DO NOT TRUNCATE.
Remember that casting truncates, and does not round.
Testing
You should put at least two test cases for this function in module a2test .
Remember that you can use the
online color conversion tool in order to find out what the
values in one color model should be in a different color model.
rgb_to_hsv(rgb)
This function converts an RGB value to an HSV value. When you get the function working,
moving the RGB sliders will cause the HSV sliders to move (but the reverse is not true).
Here is how the conversion works.
First, convert the RGB values so that R , G , and B are
in 0..1 . Let MAX be the maximum and MIN be the minimum
of the (R , G , B ) values. H will satisfy
0 ≤ H < 360 and S , V will be in 0..1 .
H is given by 5 different cases:
(a) MAX = MIN: |
H = 0 |
(b) MAX = R and G ≥ B: |
H = 60.0 * (G - B) / (MAX - MIN) |
(c) MAX = R and G < B: |
H = 60.0 * (G - B) / (MAX - MIN) + 360.0 |
(d) MAX = G: |
H = 60.0 * (B - R) / (MAX - MIN) + 120.0 |
(e) MAX = B: |
H = 60.0 * (R - G) / (MAX - MIN) + 240.0 |
S is given by: if MAX = 0 then 0, else 1 – MIN/MAX. Finally, V = MAX.
Do not round your answers. That is an unacceptable loss of precision.
When you implement this function, the numerical HSV color will display
properly in the two color panes (assuming that str5_hsv is
implemented correctly).
Testing
You will need to provide at least 5 test cases in the module a2test , so
that each expression in the cases for H is evaluated in at least one test case.
Again, remember that you can use the
online color conversion tool in order to find out what the
values in one color model should be in a different color model.
hsv_to_rgb(hsv)
This function converts an HSV value to an RGB value. Once you get it working,
everything in the GUI should work (provided that you followed instructions in order
and left this function for the end). In particular, the HSV sliders will cause the
RGB sliders to also move.
To perform the conversion, you first need to compute the following values
Hi = floor(H/60),
f = H/60 - Hi,
p = V(1-S),
q = V(1-fS),
t = V(1-(1-f)S)
Once you have this computed, the values R , G , and B
depend on
the value Hi as follows:
-
If Hi = 0, then
R = V, G = t, B = p
-
If Hi = 1, then
R = q, G = V, B = p
-
If Hi = 2, then
R = p, G = V, B = t
-
If Hi = 3, then
R = p, G = q, B = V
-
If Hi = 4, then
R = t, G = p, B = V
-
If Hi = 5, then
R = V, G = p, B = q
This produces RGB values in the range 0.0..1.0, and they must be converted to the range
0..255. You should use rounding in converting the answer to an int. We will
say it again because students have not complied in previous semesters:
ROUND; DO NOT TRUNCATE. Remember that casting truncates, and does not round.
Note: If you look at the Wikipedia entry, you will note that it uses
Hi = floor(H/60) % 6
and
f = H/60 - floor(H/60)
Because H satisfies 0 <= H < 360 (degrees), the values (floor(H/60) % 6) and
floor(H/60) are equivalent. Therefore, we use the simpler one.
Testing
In testing your code, you should provide at least 6 test cases for this function
because of the 6 possible values of Hi.
Again, remember that you can use the
online color conversion tool in order to find out
what the values in one color model should be in a different color model.
Reading the DAT Files
After all of this work, you will notice that the colorblind drop-down menu still does
not work. While you have written functions that convert from one color model to another,
you have not implemented any colorblind transformations.
However, we have already done some of this for you in a2.py. At the bottom of
the file you will notice the function apply_matrix(rgb). This function takes
a 3x3 matrix (represented as a list of list of floats) and "multiplies" it with a color
to produce a new color. So handling colorblindness is easy. We just need to find the
right 3x3 matrix.
This is the purpose of the files in the colorblind folder. Open up one of these
files in Komodo Edit. You will see that the look like this:
Deuteranomaly
0.8, 0.2, 0
0.258, 0.742, 0
0, 0.142, 0.858
The first line is the name of the colorblindness disorder, and is used by the drop-down
menu to display the choice. The next three rows are the 3x3 matrix. Each line of the
file is a row, and the columns are separated by commas.
For the last part of the assignment, you are going to write three functions that read
these files into Python and format them into lists and dictionaries for use by a2app.py.
If you are unsure of the exact format that we want from these functions, look at
a2test.py. The tests for three functions are already written for you. You
do not need to add any more test cases.
to_float_list(thelist)
Implement this function according to its specification. This function takes a list of
strings (which you are likely to have after reading from a file) and converts it into
a list of floats. Note that the preconditions do not limit you to three element lists.
You must be prepared for lists of any size.
file_to_data(filename)
This function converts a DAT file to a multi-dimensional list. The first element is the
name of the colorblindness disorder, while the remaining three elements are the rows of
the 3x3 matrix. For example, the file shown above will be converted to
['Deuteranomaly', [0.8, 0.2, 0.0], [0.258, 0.742, 0.0], [0.0, 0.142, 0.858]]
Note that the lists in the last three positions contain floats, not strings. You may
want to use the function to_float_list(thelist) to help you with this.
We ask that you implement this function according to the specification. However, there
is an additional requirement. The last three elements of the result should be appended
with a for-loop. If you are unsure of what we mean by this, ask a staff
member.
files_to_dictionary(files)
The last function is the only one actually used by a2app.py. It produces a
dictionary that maps names of colorblindness to 3x3 matrices. For example, the file
above would be in the format
{'Deuteranomaly' : [[0.8, 0.2, 0.0], [0.258, 0.742, 0.0], [0.0, 0.142, 0.858]] }
The difference between this function and file_to_data(filename) is that the
dictionary will have more than one colorblind option it. See the test in a2test.py
for an example.
Implement this function according to its specification. When you are done, try out the
drop-down menu in the GUI application. If that works, you are done with the assignment.
Finishing the Assignment
Before you submit this assignment, you should be sure that everything is working
and polished. Like the first assignment, you will be allowed to resubmit your
assignment. But we would like to limit the number of submissions, so try to to
make your first submission is fairly solid.
Once you have everything working you should go back and make sure that your
program meets the class coding conventions. In particular, you should check
that the following are all true:
-
There are no tabs in the file, only spaces (this is not an issue if you used Atom Editor).
-
Functions are each separated by two blank lines.
-
Lines are short enough (80 chars) that horizontal scrolling is not necessary.
-
The specifications for all of the functions are complete and are docstrings.
-
Specifications are immediately after the function header and indented.
Furthermore, at the top of each module that you worked on (a2.py , a2test.py )
you have three single line comments with (1) the module name, (2) your name(s) and netid(s), and
(3) the date you finished the assignment.
Upload the files a2.py and a2test.py to CMS by
the due date: |