Some material that you may find useful:
Cecilia Pendergast from the design department has produced a mock up of your page:

The idea is that clients will call up and discuss their images and proposed image thumbnails with a consultant at your company. The consultant will load your web page into their browser, plug in proposed values for the width, height, and number of colors in a GIF image, and press the button labeled to compute an estimated file size (which will show up in the area next to the label File size. The button can be used to return the form to the state you see above (with all the fields empty).
After finding a file size acceptable to the client, the
consultant sends the client the quote by entering the client's
email address into the fields at the bottom: the username goes to
the left of the @, and the mail server name goes to the
right. For example, if the client were Michael Stipe at
rem.com, the user name might be mstipe and
the server name would be rem.com.
Clicking the button will cause the email estimate
to be sent to the client for their records.
Here is a sample use of the form:
| Step 1 The user fills out the form for a 300x350 image with 200 colors. |
|
| Step 2 The user clicks the button and the file size (103 KB) appears in the form |
|
| Step 3 The user fills out the client's username and server in the
form, and then clicks the button
and the estimate is sent to the client ( |
|
hw7 in your
public_html/protected directory.assign7.html to contain
your implementation of GIF file size calculator page.Note: You can use either of the two techniques we've covered for handling alignments: tables or CSS, whichever you find easier. Just inserting non-breakable spaces, however, would represent a lower quality solution.
Math.round(). For example, Math.round(3.14)
yields the integer 3, whereas Math.round(3.99) yields the
integer 4.
(Also see the hints
below.)
Computing the bit-depth of an image relies on some mathematics that you may have forgotten since high school. Let's walk through it carefully.
Bit depth is always an integer, because it's the number of bits it takes to represent some value or set of values. It's the same as the number of decimal digits needed to count some collection of things.
Here's an example, using decimal so that it will be more intuitive. Suppose you want to enter 17 of your closest friends into the speed-dial of your cell phone. How many digits does the speed-dial number need to be? The answer, clearly, is 2, since a two-digit number gives you up to 100 numbers, while 1 digit isn't enough.
Suppose we wanted a programmatic, rather than an intuitive, solution. That is, we want to write some JavaScript that will compute the answer. Hmm. Not so obvious.
We know, intuitively, that it has to do with powers of 10:
| digits | numbers | numbers |
|---|---|---|
| 1 | 101 | 10 |
| 2 | 102 | 100 |
| 3 | 103 | 1000 |
| 4 | 104 | 10000 |
| ... | ||
| N | 10N | 10000... |
Since 17 is more than 10, we know that 1 digit won't suffice, but 2 digits give up to 100 numbers, so 2 will work fine. That is, we choose 2 because:
101 < 17 ≤ 102
In general, if we have an unknown number of close friends, call it k, we are looking to find N in an expression like:
10N-1 < k ≤ 10N
How can we do that? By definition, if you take the base 10 logarithm of a number, you find the exponent you need to raise 10 to in order to get the original number:
10N = k N = log(k)
What does this mean for our digits problem? Let's take the base 10 logarithm of each expression in our inequality:
log(101) < log(17) ≤ log(102) 1 < log(17) ≤ 2
Or, in general:
log(10N-1) < log(k) ≤ log(10N) N-1 < log(k) ≤ N
(Hang in there; we're almost done.) So, if someone gives us a k, which is the number of close friends, we can compute N, the number of digits in the speed-dial numbers as
N = log(k)
In order to figure out the bitdepth (N) for a given number of colors (k), there are now two subproblems to solve:
JavaScript supplies a lot of the standard mathematical functions, as well as some you've never heard of. These are organized by hanging them off an object called "Math." Here is a list of a JavaScript math functions. For example, you can compute the square root of a number by using Math.sqrt:
The collection of JavaScript Math functions includes a logarithm function, but it computes the natural logarithm of the parameter. The natural logs are logs base e, that magic constant that is about 2.718281828.
Fortunately, there's a way to use the natural logs to compute any log. Here's how:
| expression | explanation | ||
|---|---|---|---|
| 10N | =k | Our starting point. We know k, we want N | |
| log(10N) | =log(k) | take natural log of both sides | |
| N log(10) | =log(k) | this is a property of logarithms | |
| N | =log(k)/log(10) | divide both sides by log(10) | |
Using the equation above as a guide, play with the code in the following evaluation box so that, instead of computing the natural log, the code computes the log base 10 (also called the common log). You'll know you've succeeded when your code computes 2 on an input of 100, and 3 on an input of 1000 and so forth.
Note that you can use the same technique to compute the base two logarithm of a number. Modify your solution, above, to compute that. You'll know you've succeeded when your code computes 2 on an input of 4, 3 on an input of 8, 7 on an input of 128, and so forth.
You've now solved Subproblem A!
So, there's one problem remaining, namely that, except for the powers of 10, the result of taking the logarithm of a number is not an integer. And the number of digits, whether in binary or decimal or hexadecimal, is always an integer. So, intuitively, what do we do? We round up. For example, since the common log of 17 is 1.2304489, we would round up to 2 as the number of digits in our speed-dial list.
How can we round up in a programmatic way? The solution is yet another
built-in Math function, this one called "Math.ceil()," short for ceiling.
Try it out. The following code uses Math.random() to yield a random
number between 0 and 1, and the reciprocal of that will have a wide range.
(In principal, it could go to infinity, but in practice is usually pretty
small.) We can use Math.ceil() to round it off to the next higher number.
You've now solved Subproblem B!
We've talked about bit depth quite a lot in this course, because it's fundamental to understanding the relationship between the size of a representation and the kind of stuff you can represent. The same relationship is true whether we use binary, decimal, hexadeciaml or any number base (though not Roman numerals and other numbering systems that don't use place value), but we focus on binary because computers are binary.
The idea is essentially that if we number items using binary numbers, the number of digits in the binary number (that is, the number of bits), is closely related to how many things we can number. When dealing with GIF files, we are numbering colors, but that's irrelevant to the fundamental relationship, though it helps to be concrete in our examples.
If we want to make a picture using our 17 favorite colors, we'll need 5 bits (binary digits) to label each color. This is the same example as our speed-dial list, except in binary instead of decimal.
If we were willing to drop one of the 17 colors, we could label each color with only 4 bits, for a big savings. (5 bits down to 4 is a 20% reduction.)
Use the following form to try to figure out a JavaScript calculation that will correctly compute the bit depth for different colors. You'll know you've (probably) succeeded if you get a bit-depth of 5 for 17 colors and 4 for 16 colors, and 7 for 96 colors and 6 for 55 colors and ...
You've now figured out how to compute bit depth (y) for a given number (x) of colors!
<input type="submit"
onClick = "/* stuff I want to happen, written in JS */
return true;">
The above code will, when someone clicks on the submit button, do whatever "stuff I want to happen" and then proceed with submitting the form.