diff --git a/src/util/color.js b/src/util/color.js
index 057b68196..951cb270a 100644
--- a/src/util/color.js
+++ b/src/util/color.js
@@ -37,7 +37,7 @@ Color.decimalToHex = function (decimal) {
 /**
  * Convert a Scratch decimal color to an RGB color object.
  * @param {number} decimal RGB color as decimal.
- * @returns {RGBObject} {r: R, g: G, b: B}, values between 0-255
+ * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
  */
 Color.decimalToRgb = function (decimal) {
     var r = (decimal >> 16) & 0xFF;
@@ -51,7 +51,7 @@ Color.decimalToRgb = function (decimal) {
  * CC-BY-SA Tim Down:
  * https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
  * @param {!string} hex Hex representation of the color.
- * @return {Object} {r: R, g: G, b: B}, 0-255, or null.
+ * @return {RGBObject} null on failure, or rgb: {r: red [0,255], g: green [0,255], b: blue [0,255]}.
  */
 Color.hexToRgb = function (hex) {
     var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
@@ -68,7 +68,7 @@ Color.hexToRgb = function (hex) {
 
 /**
  * Convert an RGB color object to a hex color.
- * @param {Object} rgb {r: R, g: G, b: B}, values between 0-255.
+ * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
  * @return {!string} Hex representation of the color.
  */
 Color.rgbToHex = function (rgb) {
@@ -77,7 +77,7 @@ Color.rgbToHex = function (rgb) {
 
 /**
  * Convert an RGB color object to a Scratch decimal color.
- * @param {Object} rgb {r: R, g: G, b: B}, values between 0-255.
+ * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
  * @return {!number} Number representing the color.
  */
 Color.rgbToDecimal = function (rgb) {
@@ -96,7 +96,7 @@ Color.hexToDecimal = function (hex) {
 /**
  * Convert an HSV color to RGB format.
  * @param {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]}
- * @returns {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
+ * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
  */
 Color.hsvToRgb = function (hsv) {
     var h = hsv.h % 360;
@@ -158,12 +158,12 @@ Color.hsvToRgb = function (hsv) {
 /**
  * Convert an RGB color to HSV format.
  * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}.
- * @returns {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]}
+ * @return {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]}
  */
 Color.rgbToHsv = function (rgb) {
-    var r = rgb.r;
-    var g = rgb.g;
-    var b = rgb.b;
+    var r = rgb.r / 255;
+    var g = rgb.g / 255;
+    var b = rgb.b / 255;
     var x = Math.min(Math.min(r, g), b);
     var v = Math.max(Math.max(r, g), b);
 
@@ -185,7 +185,7 @@ Color.rgbToHsv = function (rgb) {
  * @param {RGBObject} rgb0 - the color corresponding to fraction1 <= 0.
  * @param {RGBObject} rgb1 - the color corresponding to fraction1 >= 1.
  * @param {number} fraction1 - the interpolation parameter. If this is 0.5, for example, mix the two colors equally.
- * @returns {RGBObject} the interpolated color.
+ * @return {RGBObject} the interpolated color.
  */
 Color.mixRgb = function (rgb0, rgb1, fraction1) {
     if (fraction1 <= 0) return rgb0;
diff --git a/test/unit/util_cast.js b/test/unit/util_cast.js
index 147ba2575..4f15d16bb 100644
--- a/test/unit/util_cast.js
+++ b/test/unit/util_cast.js
@@ -91,6 +91,24 @@ test('toRbgColorList', function (t) {
     t.end();
 });
 
+test('toRbgColorObject', function (t) {
+    // Hex (minimal, see "color" util tests)
+    t.deepEqual(cast.toRgbColorObject('#000'), {r: 0, g: 0, b: 0});
+    t.deepEqual(cast.toRgbColorObject('#000000'), {r: 0, g: 0, b: 0});
+    t.deepEqual(cast.toRgbColorObject('#fff'), {r: 255, g: 255, b: 255});
+    t.deepEqual(cast.toRgbColorObject('#ffffff'), {r: 255, g: 255, b: 255});
+
+    // Decimal (minimal, see "color" util tests)
+    t.deepEqual(cast.toRgbColorObject(0), {r: 0, g: 0, b: 0});
+    t.deepEqual(cast.toRgbColorObject(1), {r: 0, g: 0, b: 1});
+    t.deepEqual(cast.toRgbColorObject(16777215), {r: 255, g: 255, b: 255});
+
+    // Malformed
+    t.deepEqual(cast.toRgbColorObject('ffffff'), {r: 0, g: 0, b: 0});
+    t.deepEqual(cast.toRgbColorObject('foobar'), {r: 0, g: 0, b: 0});
+    t.end();
+});
+
 test('compare', function (t) {
     // Numeric
     t.strictEqual(cast.compare(0, 0), 0);
diff --git a/test/unit/util_color.js b/test/unit/util_color.js
index c0db8ee90..ac8761acc 100644
--- a/test/unit/util_color.js
+++ b/test/unit/util_color.js
@@ -1,6 +1,43 @@
-var test = require('tap').test;
+var tap = require('tap');
+var test = tap.test;
 var color = require('../../src/util/color');
 
+/**
+ * Assert that two HSV colors are similar to each other, within a tolerance.
+ * @param {Test} t - the Tap test object.
+ * @param {HSVObject} actual - the first HSV color to compare.
+ * @param {HSVObject} expected - the other HSV color to compare.
+ */
+var hsvSimilar = function (t, actual, expected) {
+    if ((Math.abs(actual.h - expected.h) >= 1) ||
+        (Math.abs(actual.s - expected.s) >= 0.01) ||
+        (Math.abs(actual.v - expected.v) >= 0.01)
+    ) {
+        t.fail('HSV colors not similar enough', {
+            actual: actual,
+            expected: expected
+        });
+    }
+};
+
+/**
+ * Assert that two RGB colors are similar to each other, within a tolerance.
+ * @param {Test} t - the Tap test object.
+ * @param {RGBObject} actual - the first RGB color to compare.
+ * @param {RGBObject} expected - the other RGB color to compare.
+ */
+var rgbSimilar = function (t, actual, expected) {
+    if ((Math.abs(actual.r - expected.r) >= 1) ||
+        (Math.abs(actual.g - expected.g) >= 1) ||
+        (Math.abs(actual.b - expected.b) >= 1)
+    ) {
+        t.fail('RGB colors not similar enough', {
+            actual: actual,
+            expected: expected
+        });
+    }
+};
+
 test('decimalToHex', function (t) {
     t.strictEqual(color.decimalToHex(0), '#000000');
     t.strictEqual(color.decimalToHex(1), '#000001');
@@ -60,3 +97,37 @@ test('hexToDecimal', function (t) {
     t.strictEqual(color.hexToDecimal('#00ffaa'), 65450);
     t.end();
 });
+
+test('hsvToRgb', function (t) {
+    rgbSimilar(t, color.hsvToRgb({h: 0, s: 0, v: 0}), {r: 0, g: 0, b: 0});
+    rgbSimilar(t, color.hsvToRgb({h: 123, s: 0.1234, v: 0}), {r: 0, g: 0, b: 0});
+    rgbSimilar(t, color.hsvToRgb({h: 0, s: 0, v: 1}), {r: 255, g: 255, b: 255});
+    rgbSimilar(t, color.hsvToRgb({h: 321, s: 0, v: 1}), {r: 255, g: 255, b: 255});
+    rgbSimilar(t, color.hsvToRgb({h: 0, s: 1, v: 1}), {r: 255, g: 0, b: 0});
+    rgbSimilar(t, color.hsvToRgb({h: 120, s: 1, v: 1}), {r: 0, g: 255, b: 0});
+    rgbSimilar(t, color.hsvToRgb({h: 240, s: 1, v: 1}), {r: 0, g: 0, b: 255});
+    t.end();
+});
+
+test('rgbToHsv', function (t) {
+    hsvSimilar(t, color.rgbToHsv({r: 0, g: 0, b: 0}), {h: 0, s: 0, v: 0});
+    hsvSimilar(t, color.rgbToHsv({r: 64, g: 64, b: 64}), {h: 0, s: 0, v: 0.25});
+    hsvSimilar(t, color.rgbToHsv({r: 128, g: 128, b: 128}), {h: 0, s: 0, v: 0.5});
+    hsvSimilar(t, color.rgbToHsv({r: 192, g: 192, b: 192}), {h: 0, s: 0, v: 0.75});
+    hsvSimilar(t, color.rgbToHsv({r: 255, g: 255, b: 255}), {h: 0, s: 0, v: 1});
+    hsvSimilar(t, color.rgbToHsv({r: 255, g: 0, b: 0}), {h: 0, s: 1, v: 1});
+    hsvSimilar(t, color.rgbToHsv({r: 0, g: 255, b: 0}), {h: 120, s: 1, v: 1});
+    hsvSimilar(t, color.rgbToHsv({r: 0, g: 0, b: 255}), {h: 240, s: 1, v: 1});
+    t.end();
+});
+
+test('mixRgb', function (t) {
+    rgbSimilar(t, color.mixRgb({r: 10, g: 20, b: 30}, {r: 30, g: 40, b: 50}, -1), {r: 10, g: 20, b: 30});
+    rgbSimilar(t, color.mixRgb({r: 10, g: 20, b: 30}, {r: 30, g: 40, b: 50}, 0), {r: 10, g: 20, b: 30});
+    rgbSimilar(t, color.mixRgb({r: 10, g: 20, b: 30}, {r: 30, g: 40, b: 50}, 0.25), {r: 15, g: 25, b: 35});
+    rgbSimilar(t, color.mixRgb({r: 10, g: 20, b: 30}, {r: 30, g: 40, b: 50}, 0.5), {r: 20, g: 30, b: 40});
+    rgbSimilar(t, color.mixRgb({r: 10, g: 20, b: 30}, {r: 30, g: 40, b: 50}, 0.75), {r: 25, g: 35, b: 45});
+    rgbSimilar(t, color.mixRgb({r: 10, g: 20, b: 30}, {r: 30, g: 40, b: 50}, 1), {r: 30, g: 40, b: 50});
+    rgbSimilar(t, color.mixRgb({r: 10, g: 20, b: 30}, {r: 30, g: 40, b: 50}, 2), {r: 30, g: 40, b: 50});
+    t.end();
+});