Jump to content
Search Community

Hue values around the color wheel not saturated as expected

JimmiQR test
Moderator Tag

Recommended Posts

I am using version 12.0, and I am wondering if this hue situation is a bug, or a limitation. I expect to take a solid colored object, adjust its hue around the 360 color wheel, and get a solid color back, but the colors I get are muddled. The saturation is off.

 

I make a solid green object of 0x00FF00 (100% green). When I adjust the hue by 180, I expect it to go to the opposite side of the RGB color wheel to 100% purple, but it goes to 0xFF6EFF, or 255 for red and blue, as expected, but a green value of 110 (not 0), giving me a muddled purple. Similarly, when I try to adjust the same bright green object to bright red, using a hue adjustment of 240, it is a muddled red.

 

I poked into the code, and see the use of Luminosity constants for R, G, and B at 0.212671, 0.715160, and 0.072169. Perhaps these are not the best constants? Perhaps the algorithm for hue adjustment on line 165 in ColorMatrixPlugin.as in version 12.0 is incorrect?

var c:Number = Math.cos(n),
s:Number = Math.sin(n),
temp:Array = [(_lumR + (c * (1 - _lumR))) + (s * (-_lumR)), (_lumG + (c * (-_lumG))) + (s * (-_lumG)), (_lumB + (c * (-_lumB))) + (s * (1 - _lumB)), 0, 0, (_lumR + (c * (-_lumR))) + (s * 0.143), (_lumG + (c * (1 - _lumG))) + (s * 0.14), (_lumB + (c * (-_lumB))) + (s * -0.283), 0, 0, (_lumR + (c * (-_lumR))) + (s * (-(1 - _lumR))), (_lumG + (c * (-_lumG))) + (s * _lumG), (_lumB + (c * (1 - _lumB))) + (s * _lumB), 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1];

It is pretty complex, as I assume it needs to be, but could there be something askew in there?

 

 

If I use a bright green object of 0x00FF00, and adjust the hue value by 60, 120, 180, 240, or 300; I was hoping I could get bright versions of teal, blue, purple, red, yellow. but it appears I can not get bright objects out of the hue transformation function.

 

[in my attached image, I use two identical looking bright green circles, and adjust the right one to get bright red using code, but it does not come out as bright red.

TweenMax.to(adjustedSprite, 1, {colorMatrixFilter:{hue:240 }} );

 

I remember reading about how Flash doesn't always work like Photoshop does, but this is just a color wheel hue issue, no?

 

Thanks in advance, jimmi.

post-12221-0-63661100-1357410599_thumb.jpg

Link to comment
Share on other sites

I have been poking around some more, and now I am really confused as to what the hue property is supposed to do. I also lack an art background, so I could be interpreting the color wheel incorrectly.

 

I generated 6 circles, all solid primary and secondary light-based colors. Red, Green, Blue, Yellow, Purple, Teal. Then I created 6 more circles from each base circle and adjusted the hue of each of those colors by a degree of 60. I was still expecting bright colors that fall on the perimeter of this color wheel model: http://bluelobsterar...or-wheel-lg.jpg . More specifically, I was expecting to be able to generate a bright RGBYTP from each of those bases. I was shocked to see grays, pastels, and earth tones from a hue adjustment of bright colors.

 

Each of my 6 bases generated uniquely unexpected results [attached]

 

I generated those with this code:

 

for (var j:int = 0; j < 6; j++) {
for (var i:int = 0; i < 7; i++) {
var sprite:Sprite = new Sprite();
var baseColor:uint;
if (j == 0) baseColor = 0xFF0000;
if (j == 1) baseColor = 0x00FF00;
if (j == 2) baseColor = 0x0000FF;
if (j == 3) baseColor = 0xFFFF00;
if (j == 4) baseColor = 0xFF00FF;
if (j == 5) baseColor = 0x00FFFF;
sprite.graphics.beginFill(baseColor);
sprite.graphics.drawEllipse(40 * i + 10, 300 + (60 * j) + 10, 40, 40);
addChild(sprite);
TweenMax.to(sprite, .5, {colorMatrixFilter:{hue:i * 60 }} );
}
}

 

I have no idea what I am doing wrong.

post-12221-0-76816100-1357421726_thumb.jpg

Link to comment
Share on other sites

The goal with the ColorMatrixFilterPlugin's hue functionality was to mimic what Adobe does in the Flash IDE. I checked and it looks like the results you're reporting are pretty much exactly what Flash does too. Select a MovieClip instance on the stage, apply a ColorMatrixFilter (select the "adjust color" option) and then mess with the "hue" value. See what I mean? I don't think Adobe's intent was to mimic Photoshop's functionality (although as a user, I wish they would)

Link to comment
Share on other sites

Thank you very much. Yes, I replicated what you said, and I too see that now. Grrrr. That is very unfortunate for me (and I assume others). This has been bothering me for a few days, and I really hope I didn't hit a wall with this.

 

I drew circles in a smoother gradient using your (and Adobes) hue algorithm to see a better pattern of what was happening.

6-colors-all-hue-adjusted-by-10-degrees.jpg

In the drawing above, many starting colors can not be hue-adjusted to many other colors. Take trying to convert to yellow, for example!

 

Now it appears my situation is beyond the GreenSock Animation Platform and is a core Flash problem, and I thank you for your response. But I would like to leave this one last and very specific situation here for you and future readers to ponder/confirm. So, based on everything I have learned on this to date, if someone wants to adjust a dynamic complex bitmap that contains grays and purple to a complex bitmap that contains yellow and maintains the grays, (very common in Photoshop and game design) they are out of luck? In AS3 anyway?

 

complex-purple-to-complex-yellow.jpg

 

 

(at the very least, this is quite a colorful thread)

Link to comment
Share on other sites

Actually, I have good news for you. I'm pretty sure the effect shown here is what you are after:

http://snorkl.tv/dev/blendModes/

 

That is accomplished using blendmode:overlay on a solid colored circle sitting in a layer above the circle with the white to black radial gradient. The solid circle simply has its tint tweened.

 

 

import com.greensock.*;
import com.greensock.easing.*;
import flash.display.Sprite;
import flash.events.MouseEvent;

var colors_arr:Array = [
0xff0000,
0xff6600,
0xffff00,
0x66ff00,
0x00ff00,
0x00ff66,
0x00ffff,
0x0066ff,
0x0000ff,
0x0000ff,
0x6600ff,
0xff00ff,
0xff0066
];

for(var i = 0; i < colors_arr.length; i++){
 var circle= new MovieClip();
 circle.graphics.beginFill(colors_arr[i]);
 circle.graphics.drawEllipse(i *45, 150 + 10, 40, 40);
 circle.tint = colors_arr[i];
 circle.addEventListener(MouseEvent.ROLL_OVER, overcircle);
 circle.buttonMode = true;
 addChild(circle);
}

function overcircle(e:MouseEvent):void {
 TweenMax.to(mc, .5, {tint:e.target.tint});
}

 

CS5 source attached (use your own greensock lib) .

 

Let us know if this works for you.

 

Also, I want to thank you for taking the time to so clearly explain your issue and provide the sample code and images. Its a huge help.

 

-Carl

blendmode_overlay_CS5.zip

Link to comment
Share on other sites

Carl, thanks so much for working out other solutions to this problem. I checked out your code and pulled down the files to explore it. This effect you laid out only solves part of the problem. Your example does not take into account images that have gray tones, as my eyeballs, or ringed domes do. Also, your solution assumed I would only need to mask a circle, rather than a complex photograph or something similar. (I used a circle shape only as a color example). But that is ok, I explored it further.

 

But what you created made me realized you still had a great start, and I am always amazed at what blendModes can do visually. If I would create two images from a single one in a photo editing program, one as the gray scale, one as the mask to be tinted, I could get the effect I am looking for, even with a complex object. It would involve your solution, with a hybrid of my second png as a tinted mask of sorts. You could make the tie and beer be any color, with vibrant colors of your choosing.

man-with-hue-beer-and-tie.jpg

 

This would not be as flexible as I was hoping, as the images could not be that dynamic, but would require creating a mask to tint first.

 

 

Then, I finally solved it all!!

 

In my application, I create these assets that need to have shades of gray and shades of a color as a base of green. Then I hardcode values into a ColorMatrixFilter function that will turn values of green into vibrant equivalents in red, blue, yellow, purple, and teal. No muddle colors!

 

This solution may be more specific to me, than in general, because I set a rule that my art assets that require this hue effect will all start with a base of green (as in green-screen). Also, I pass in ints into my function that represent colorcodes already in my application. But others can work with this and tweak it.

public static function getHueFilter(colorId:int):ColorMatrixFilter {
// assumes starting from green based bitmap
var matrix:Array = new Array();
switch (colorId) {
case 0://green to red
matrix = matrix.concat([0, 1, 0, 0, 0]);
matrix = matrix.concat([1, 0, 0, 0, 0]);
matrix = matrix.concat([1, 0, 0, 0, 0]);
break;
case 1://just green
matrix = matrix.concat([1, 0, 0, 0, 0]);
matrix = matrix.concat([0, 1, 0, 0, 0]);
matrix = matrix.concat([0, 0, 1, 0, 0]);
break;
case 2://green to blue
matrix = matrix.concat([1, 0, 0, 0, 0]);
matrix = matrix.concat([1, 0, 0, 0, 0]);
matrix = matrix.concat([0, 1, 0, 0, 0]);
break;
case 3://green to yellow
matrix = matrix.concat([0, 1, 0, 0, 0]);
matrix = matrix.concat([0, 1, 0, 0, 0]);
matrix = matrix.concat([1, 0, 0, 0, 0]);
break;
case 4://green to purple
matrix=matrix.concat([0,1,0,0,0]);
matrix=matrix.concat([1,0,0,0,0]);
matrix=matrix.concat([0,1,0,0,0]);
break;
case 5://green to teal
matrix = matrix.concat([1, 0, 0, 0, 0]);
matrix = matrix.concat([0, 1, 0, 0, 0]);
matrix = matrix.concat([0, 1, 0, 0, 0]);
break;
}
matrix = matrix.concat([0, 0, 0, 1, 0]);// alpha
return new ColorMatrixFilter(matrix);
}

Was I completely oblivious to not realize this earlier? Perhaps I should have.

 

The thing I didn't understand during my frustratingly long search for a proper hue function, is why no one wrote one! Even what I am showing is not proper, as it only outputs very specific colors, RGBYTP. But in the 20+ lost hours I tackled this problem, I did not find one example, class, or package that did this for Actionscript. I don't know the visual math enough to tackle the full 360 wheel in a single algorithm but someone surely does, no? I think it would be so handy. It is one of those tools no one knows they need, until they are shown just how broken the built in Flash hue feature really is. Perhaps a plugin for Club GreenSock ;) True Hue™? (That's a freeby)

 

Thanks Carl for all your help!!

  • Like 1
Link to comment
Share on other sites

You're very welcome, Jimmi.

 

Very glad to hear you found a suitable solution. I'm quite impressed with it.

 

I appreciate the TrueHue suggestion. Clever name;) We are buried with more pressing needs surrounding the platform but will definitely make a note of this and let you know if this type of plugin gets implemented.

 

Thanks again for all the time you put into your posts. I'm sure it will serve others who have similar needs.

 

Best,

 

Carl

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...