User Tools

Site Tools


cs19s23as07

cs19s23as07: HSV Color Class

Goals

  • Practice with object-oriented design and operator overloading in C++.
  • Learn a bit about color representation and color theory.

Prerequisites

This assignment requires familiarity with the lecture materials presented in class through week 07.


Background

Image showing different kinds of RGB pixels on different kinds of displays. Courtesy https://commons.wikimedia.org/wiki/File:Pixel_geometry_01_Pengo.jpg

You may be familiar with RGB colors, and/or the RGB color model. It's a pretty simple idea, where values representing an amount of red, green, and blue light are “added” together to form a color. This is a common representation due to the fact that the pixels on most screens (such as LCDs and CRTs) are generated by devices that emit red, green or blue light, mainly because those are three wavelengths of light to which human eyes are most sensitive (for fairly obvious reasons).

As per the arbiter of all human information:

HSL (for hue, saturation, lightness) and HSV (for hue, saturation, value; also known as HSB, for hue, saturation, brightness) are alternative representations of the RGB color model, designed in the 1970s by computer graphics researchers to more closely align with the way human vision perceives color-making attributes. In these models, colors of each hue are arranged in a radial slice, around a central axis of neutral colors which ranges from black at the bottom to white at the top.

Illustration of the three components of the HSV color model on a cylinder, where the distance from the vertical center shows increasing saturation, values increase vertically, and hues are uniformly distributed around the circumference of the cylinder. Courtesy https://commons.wikimedia.org/wiki/File:HSV_color_solid_cylinder.png

Using a representation like HSV makes it much easier to modify and interpret colors in an intuitive way, such as calculating complementary colors or varying a color's apparent brightness/intensity.

<html> <label for=“color-picker”>Select a color to see its description in RGB and HSV:</label> <input type=“color” id=“color-picker” name=“color-picker” value=“#6495ed” style=“display:block; width: 200px; height: 200px; float: right;”>

<script> function rgb2hsv (r, g, b) {

  let rabs, gabs, babs, rr, gg, bb, h, s, v, diff, diffc, percentRoundFn;
  rabs = r / 255;
  gabs = g / 255;
  babs = b / 255;
  v = Math.max(rabs, gabs, babs),
  diff = v - Math.min(rabs, gabs, babs);
  diffc = c => (v - c) / 6 / diff + 1 / 2;
  percentRoundFn = num => Math.round(num * 100) / 100;
  if (diff == 0) {
      h = s = 0;
  } else {
      s = diff / v;
      rr = diffc(rabs);
      gg = diffc(gabs);
      bb = diffc(babs);
      if (rabs === v) {
          h = bb - gg;
      } else if (gabs === v) {
          h = (1 / 3) + rr - bb;
      } else if (babs === v) {
          h = (2 / 3) + gg - rr;
      }
      if (h < 0) {
          h += 1;
      }else if (h > 1) {
          h -= 1;
      }
  }
  return {
      h: Math.round(h * 360),
      s: percentRoundFn(s),
      v: percentRoundFn(v)
  };

} function describeColor(event) {

let hexString = event.target.value;
let div = document.getElementById("color-description");
while (div.firstChild)
  div.removeChild(div.firstChild);
let list = document.createElement('ul');
div.appendChild(list);

let itemHexString = document.createElement('li');
itemHexString.style.color = 'black';
itemHexString.innerHTML = `Hex string: <code>${hexString}</code>`;
list.appendChild(itemHexString);

let itemRed = document.createElement('li');
itemRed.style.color = 'red';
let redHex = hexString.slice(1, 3);
let red = parseInt(redHex, 16);
itemRed.innerHTML = `Red component: <code>0x${redHex} ${red}</code>`;
list.appendChild(itemRed);

let itemGreen = document.createElement('li');
itemGreen.style.color = 'green';
let greenHex = hexString.slice(3, 5);
let green = parseInt(greenHex, 16);
itemGreen.innerHTML = `Green component: <code>0x${greenHex} ${green}</code>`;
list.appendChild(itemGreen);

let itemBlue = document.createElement('li');
itemBlue.style.color = 'blue';
let blueHex = hexString.slice(5);
let blue = parseInt(blueHex, 16);
itemBlue.innerHTML = `Blue component: <code>0x${blueHex} ${blue}</code>`;
list.appendChild(itemBlue);
let itemRgbString = document.createElement('li');
itemRgbString.style.color = 'black';
itemRgbString.innerHTML = `RGB string: <code>rgb(${red},${green},${blue})</code>`;
list.appendChild(itemRgbString);
let hsv = rgb2hsv(red, green, blue);

let itemHue = document.createElement('li');
itemHue.style.color = 'black';
itemHue.innerHTML = `Hue: <code>${hsv.h}</code>`;
list.appendChild(itemHue);

let itemSaturation = document.createElement('li');
itemSaturation.style.color = 'black';
itemSaturation.innerHTML = `Saturation: <code>${hsv.s}</code>`;
list.appendChild(itemSaturation);

let itemValue = document.createElement('li');
itemValue.style.color = 'black';
itemValue.innerHTML = `Value: <code>${hsv.v}</code>`;
list.appendChild(itemValue);

} document.getElementById(“color-picker”).addEventListener(“change”, describeColor, false); document.getElementById(“color-picker”).dispatchEvent(new Event(“change”)); </script> </html>


Assignment

You shall create a class in the cs19 namespace named HsvColor, defined in header file cs19_hsv_color.h and implemented in file cs19_hsv_color.cpp. Instances of cs19::HsvColor represent immutable HSV colors, where each of the three components (hue, saturation and value) of a color is represented as a float. cs19::HsvColor also offers a few overloaded operators and other functions, including several related to converting a HSV color to its equivalent 24-bit RGB components.

Specifically, design your class to accommodate at least the public functions specified in this documentation. You may add other functions if you'd like, as long as they don't interfere with the expected functionality.

Once the basic parts of your class are complete, you can try running this demo code that exercises class cs19::HsvColor and produces an HTML document on standard output. If your class has enough functionality to support this demo, it should produce a web page identical to this one. You can try the following and compare your results with those expected:

g++ hsv_color_demo.cpp cs19_hsv_color.cpp -o hsv_color_demo
./hsv_color_demo >~/public_html/hsv_color_demo.html

Now visit the following URLs and compare them visually to check for any discrepancies:

  • jeff.cis.cabrillo.edu/datasets/docs_cs19_hsv_color/hsv_color_demo.html
  • jeff.cis.cabrillo.edu/~/hsv_color_demo.html

Tips

  • No need to really know anything about hexadecimal numbers if you're totally unfamiliar. <iostream> makes it very easy to print and parse integers formatted in hexadecimal into output streams and from input streams.
  • Feel free to find and cite pre-existing code that can convert from HSV to RGB, unless you want to write it from scratch.
  • There are plenty of online tools for checking whether your conversions between HSV and RGB are correct.

Submission

Submit cs19_hsv_color.h and cs19_hsv_color.cpp via turnin.

Feedback Robot

This project has a feedback robot that will run some tests on your submission and provide you with a feedback report via email within roughly one minute.

Please read the feedback carefully.

Due Date and Point Value

Due at 23:59:59 on the date listed on the syllabus.

Assignment 07 is worth 60 points.

Possible point values per category:
---------------------------------------
Class functionality                  60
  (split as evenly as possible
   between member functions)
Possible deductions:
  Style and practices            10–20%
Possible extra credit:
  Submission via Git                 5%
---------------------------------------
cs19s23as07.txt · Last modified: 2023-03-27 17:22 by 127.0.0.1