Posts tagged ‘color’

Trolltech / Nokia Qt – Styles Could Be More … Stylish

One of the great things about Trolltech’s hard work into Qt has been the ability to use styles.  It’s a great concept, not only that you can tailor your application to a native look and feel at the drop of a hat simply by switching the style used, but that you can even derive your own style from QStyle (or any style based on QStyle) to create your own look and feel.

It’s absolutely great!

…Except for when it doesn’t work.

I won’t even begin to go into a long rant on just exactly why the native-OS styles don’t have “emulation” to execute on non-native platforms (the very point of using Qt), even if it is at a performance loss.  No, that Epic Fail  is blatantly obvious and doesn’t need a whole blog entry just on its own.

No, what I’m going to talk about today is where styles are broken.

Take, for example, the great ability to use a brush instead of a color in a palette.  In this way you can, most obviously, turn a background into not just a solitary color, but a pixmap, or even a gradient.  You can do all sorts of funky things with brushes.  It’s a wonderful concept in Qt.  … Except for when it doesn’t work.

Now I don’t know just how many styles this affects, but I do know that while basing a custom style on QCleanlooksStyle I found a number of bugs, and while walking through some of them through the debugger they step back through QCleanlooksStyle into QWindowsStyle and even QCommonStyle.  Now I get how some of these have been around for so long that maybe somehow someone just forgot that they needed upgrading.

Maybe.

Even if the ability to use a background pixmap has been around since Qt 3…

Or maybe there were just some serious bugs in Qt4.7.0.  (When will Nokia get around to actually releasing the 4.7.3 SDK instead of a “release candidate”?  And why didn’t they release a 4.7.1 or 4.7.2 SDK?  For professional developers who don’t work off of anything “official” this is a grievous oversight.)  But suffice it to say, turn on QCleanlooksStyle and then set your palette’s Window brush to, say, a gradient, and BAM! Bugs.

I think one of my favorite, one of the perfect examples, happens to reside right in QCleanlooksStyle itself.  One of the nice things about Qt is that you can look at the code.  And right there in drawControl, is little old QStyle::CE_Splitter.  Now I love that the Linux world has taken things like splitters and sliders and made them more … visible.  Lines and circles and dashes and all sorts of visual cues that this is something you want to touch.  In other styles things like splitters can be darned hard to realize are movable objects.

But, one of the epic fails in the Cleanlooks implementation of the splitter is … the failure to properly support the brush of the palette.  As soon as you un-colorify your palette, you’re asking for trouble.  Because plenty of things in styles, like splitter, like frames for that matter, just assume that you want to fill in an area of space with a color.  And be it a bug or by intent, at least in version 4.7.0, once you set a palette to use a brush it nukes the color.  So if you ask for the color specifically, you just get black.  And so all of those nicely colored areas are suddenly filled with black.  Black splitters.  To say it doesn’t look right is an understatement.  And all because they try to fill a rect with a palette’s Window color.

Now, of course the easy solution would be to use the frigging brush! Obviously.

But the thing is, they’re trying to be fancy, to say, highlight a selected splitter by lightening up the color.  Which works if your palette is only drawing with colors.  But works not at all if your palette is brush-happy.

And yet, there’s an easy better fix.  Instead of filling a rect with a 5% lighter color, why not use the awesome power of Qt to do something even better?  Set the painter’s opacity to 5% and paint a white rect instead.  Because that works just great with both color and brush.

Is it really too much to ask that the Trolls do a simple validation of their styles by setting a simple QLinearGradient Window brush to test the drawing of each and every style?

I can only hope that in future versions of Qt (heck, hopefully in the 7.4.3 SDK if it ever gets past beta into actual release) all of these style bugs can be fixed so that the beauty of Qt can truly shine.

Triton Is Not Just A Myth – It’s A Real Color E Ink Display

Well, it has finally happened.  Electronic ink has gone color!

One of the biggest complaints of e-book readers is that they’re black and white.  A lot of people figured that we’d have to go to OLED screens or some such to finally get some color, which goes completely against the grain of the whole e-book concept which has been the e-ink basis.  That’s because e-ink displays are readable in sunlight, use very little power, and can even still be read when turned off.  They’re not the typical LCD / OLED screen technology used in cell phones and laptops that suck up electricity like candy and can be challenging to read in sunlight.  But so far, electronic ink has only been black and white.

Until now!

E Ink, pretty much the company when it comes to, you guess it, e-ink, has just unveiled their latest creation: Triton!  Triton isn’t just a mythical Greek god anymore.  Now it’s also a a 4-bit color e-ink screen.

Umm … 4-bit?  Really?  Is that all?

That’s like 16 colors…

Okay, not exactly.  E Ink claims that Triton can display 4096 colors.  So then when they say 4-bit, they mean 4 bits per channel, and there are 3 color channels: Red, Green, and Blue; a cumulative total of 12-bits.    So since 2 to the 4th power is 16, that’s 16 shades of red, 16 shades of green, and 16 shades of blue, for 4096 possible combinations to make every color that you’d ever …

Wait a minute!

That’s it?  4096?!  I’ve seen more colors in a box of crayons!

Wow, we’re going way back into the late ’80s / early ’90s here to get that few colors.  Like Commodore Amiga days here.  I mean computers have had at least 16-bit color depths (65536 colors) for like … forever.  I mean computers have been using 24-bit depth (16 million colors) forever.  Heck, they’ve been using 32-bit depth (4 billion colors) for a while now.

So instead of a modern 4 billion colors, E Ink’s Triton display only does 4 thousand?

Yeah.

Bummer.

Still, it’s color at least.  It’s a start.  Because electronic ink is very different from CRT, LCD, or OLED technology.  It has to start somewhere.  And as you look at the marketing material for the Triton screen, you quickly realize that’s just exactly what it is, the beginning.

E Ink's Triton 4096 color e-ink display

E Ink's Triton 4096 color e-ink display

The colors are … less than stunning.  They’re washed out by a lack of contrast and color depth.  It’s almost literally like looking at a color newspaper print.  It’s far from the glam that a glossy magazine page delivers.  Or from any modern color display.  Except that it’s e-ink, not printed ink, and not backlit LCD crystals.  It’s a start.  And frankly, I’m sure a lot of e-book reader users out there will be overjoyed at the escape from the monotony of black and white.

And like a good wine, or pretty much every piece of technology invented ever, it will only get better with age.

Just when we’ll start seeing Kindles and Nooks and such with color displays of the likes of E Ink’s Triton is anyone’s guess.  Not likely in time for Christmas.  But soon.

The real question will be, what kind of price premium will color electronic ink demand?

Red Green Blue To Red Yellow Blue – Part 2

Okay, so I kind of forgot to finish up my work on converting a Red Green Blue color system to a Red Yellow Blue color system.  For those of you who don’t remember (and who would) here is the basic recap:

Since the dawn of time, children have been taught their primary colors: Red, Yellow, and Blue.  And they have been taught their secondary colors: Red and Yellow make Orange, Yellow and Blue make Green, Blue and Red make Violet (otherwise known as Purple).  It’s a simple system.  We all know it.  Artists have been using it forever.

The Red Yellow Blue Color Wheel

The Red Yellow Blue Color Wheel

And computers have these lovely computer programs that have all sorts of neat artistic tools.  There’s Adobe Photoshop, GIMP, Paint Shop Pro, even MS Paint.  The list goes on virtually forever.  But they all have one basic flaw:  They don’t use the same color system as artists do.

What?

I know!

Computers base their color system on the invention of the monitor, which itself is based on the color TV.  And these devices base their colors on the light spectrum, which has the primary colors of Red, Green, and Blue.  Making for secondary colors where Red and Green makes Yellow, Green and Blue makes Cyan, and Blue and Red makes Magenta.

The Red Green Blue Color Wheel

The Red Green Blue Color Wheel

Somehow this RGB (or sometimes known as CMY ) color system has dominated computers, so much so that software doesn’t even try to give users an option of a Red Yellow Blue color system.

Until now!

Yes, that’s right.  I, Arah J. Leonard, have written a bit of Python code (though the formulas should translate easily into any language) that converts RGB to RYB and back again.  And let me tell you, it makes a huge difference in calculating complementary colors!  Using this bit of code you can make, for example, button text that always stands out correctly against the color of a button.

And I’m making the code free to use, to all, and free to distribute.  It’s licenced under the LGPL and the MIT License both, giving you the option to use and/or distribute this under either one license (or both) as your project needs.  Use it to your heart’s content folks!  Download your free copy of rgb2ryb.py to convert between Red Green Blue (RGB) and Red Yellow Blue (RYB).

Enjoy!

# Author: Arah J. Leonard
# Copyright 01AUG09
# Distributed under the LGPL - http://www.gnu.org/copyleft/lesser.html
# ALSO distributed under the The MIT License from the Open Source Initiative (OSI) - http://www.opensource.org/licenses/mit-license.php
# You may use EITHER of these licenses to work with / distribute this source code.
# Enjoy!

# Convert a red-green-blue system to a red-yellow-blue system.
def rgb2ryb(r, g, b):
	t = type(r)

	# Remove the whiteness from the color.
	w = float(min(r, g, b))
	r = float(r) - w
	g = float(g) - w
	b = float(b) - w

	mg = max(r, g, b)

	# Get the yellow out of the red+green.
	y = min(r, g)
	r -= y
	g -= y

	# If this unfortunate conversion combines blue and green, then cut each in half to preserve the value's maximum range.
	if b and g:
		b /= 2.0
		g /= 2.0

	# Redistribute the remaining green.
	y += g
	b += g

	# Normalize to values.
	my = max(r, y, b)
	if my:
		n = mg / my
		r *= n
		y *= n
		b *= n

	# Add the white back in.
	r += w
	y += w
	b += w

	# And return back the ryb typed accordingly.
	return t(r), t(y), t(b)

# Convert a red-yellow-blue system to a red-green-blue system.
def ryb2rgb(r, y, b):
	t = type(r)

	# Remove the whiteness from the color.
	w = float(min(r, y, b))
	r = float(r) - w
	y = float(y) - w
	b = float(b) - w

	my = max(r, y, b)

	# Get the green out of the yellow and blue
	g = min(y, b)
	y -= g
	b -= g

	if b and g:
		b *= 2.0
		g *= 2.0

	# Redistribute the remaining yellow.
	r += y
	g += y

	# Normalize to values.
	mg = max(r, g, b)
	if mg:
		n = my / mg
		r *= n
		g *= n
		b *= n

	# Add the white back in.
	r += w
	g += w
	b += w

	# And return back the ryb typed accordingly.
	return t(r), t(g), t(b)

# Return the complementary color values for a given color.  You must also give it the upper limit of the color values, typically 255 for GUIs, 1.0 for OpenGL.
def complimentary(r, g, b, limit=255):
	return limit - r, limit - g, limit - b

# Debugging test code.  Not intended to be used as an application.
if __name__=="__main__":
	red = (255, 0, 0)
	green = (0, 255, 0)
	blue = (0, 0, 255)
	cyan = (0, 255, 255)
	magenta = (255, 0, 255)
	yellow = (255, 255, 0)
	black = (0, 0, 0)
	white = (255, 255, 255)
	orange = (255, 128, 0)
	darkgreen = (0, 128, 0)
	tests = [red, green, blue, cyan, magenta, yellow, black, white, orange, darkgreen, (255, 128, 64), (255, 64, 128), (64, 255, 128), (128, 255, 64), (64, 128, 255), (128, 64, 255)]
	for test in tests:
		ryb = rgb2ryb(test[0], test[1], test[2])
		rgb = ryb2rgb(ryb[0], ryb[1], ryb[2])
		cryb = complimentary(ryb[0], ryb[1], ryb[2])
		crgb = ryb2rgb(cryb[0], cryb[1], cryb[2])
		print test, "rgb2ryb", ryb, "ryb2rgb", rgb
		print "complimentary rgb", complimentary(rgb[0], rgb[1], rgb[2])
		print "complimentary ryb", cryb, "to rgb", crgb
		print

Red-Green-Blue To Red-Yellow-Blue – Part 1

I already solved this once, a long while back.  And it was handy code to have.  But unfortunately I lost the code.  So now I’m re-solving the problem.  How do you convert from a red-green-blue color scheme (that typically used by computers) into a red-yellow-blue “primary colors” color scheme (that typically used by artists)?

I guess I should explain why this is useful.  From the time we’re born our mommies and daddies give us primary colors of red, yellow, and blue.  And we know that yellow and blue make green.  And that the opposite of red is green.  They’re complementary colors.  Anyone who has ever painted, drawn, etc. knows it.  Anyone who has ever taken even a basic art class knows it.  Heck, anyone who’s ever peed into a toiled filled with blue water knows it.  Primary and secondary colors are all around us.  From the day we’re born to the day we die, it’s the color system we know like the backs of our hands.

But those of us who have done graphics work on computers know that colors don’t work that way … on a computer.  Computers don’t use this color system.  Computers use a red, green, and blue color system.  It’s based on light wavelengths.  Red plus green makes yellow.  The opposite color of red is cyan, not green.  (Hence the other related color system based on the opposites of rgb: cyan, magenta, and yellow or cmy.)  It makes sense to anyone who understands light wavelengths, like a scientist.  But to a graphical artist trying to do work on a computer it can be downright confusing if not insanely ludicrous.  I mean just try taking your painting and doing a color inversion.  It doesn’t come out anything like you’d expect.  Your years of artistic knowledge completely fail you when you hop onto a computer.  All because computer monitors are based on light, so computers have always, from the very beginning, been designed in a way to display the proper images on your monitor; not to help you paint a picture.

Now you’d think that every graphics program ever written would therefor have a way to switch from the rgb color system to the ryb color system, because surely graphical artists use graphics programs, right?

Strangely, I’ve yet to see it.  Granted, it’s been a while since I looked at the biggies like Photoshop and Paint Shop Pro (I have used both in the past).  These days I’ve been using GIMP, because it’s free, and once you get used to the eccentricities, it’s darn near as good as Photoshop at nearly everything.

But where I’ve really needed it is in writing GUIs.  Say you’ve got a GUI where you’re describing a crystal.  You want a way to pick the crystal’s color.  You make buttons to choose colors.  Well the names of the colors on the buttons is great, but wouldn’t it be even neater to colorize the buttons themselves?  It’s easy enough to do.  (At least when using Trolltech’s Qt.  MFC makes it a tad more of a challenge.)  So you set the background color of the button widgets to the color defined by the button text.  It’s insanely easy, and pretty effective … for most colors.  But then there’s that nagging problem, some background colors make black text kind of hard to read.  Especially, you know, black.  Black on black is a bit of a challenge to read.  So you want to make the text always a good color.

Now, you can write an algorithm to calculate the luminosity of the rgb value and determine if white or black would contrast more against the button.  Which works.  But it’s kind of a … kluge.  It doesn’t look nearly as professional as it should.

So you take it one step further.  You use an algorithm to get the contrasting color of the rgb value.  It works.  But looks positively awful.  Because scientifically we know the opposing light wavelength to red is cyan, artistically, our whole life tells us that the opposite color of red is green.  And so the rgb-inverse method grates on our sensibilities.  It makes for readable text, but psychologically drives us nuts.

Which is what brings us to the ultimate solution: a rgb to ryb color system change.  Because once we work in an ryb color system, then the inverse of red really is green.  It does wonders for our GUIs, making the text readable and comforting in its simple “rightness”.  And maybe one day it’ll bring relief to graphical artists on computers when you can switch from rgb to ryb in GIMP or Photoshop and suddenly everything makes sense.

So that’s the explanation.  What’s the solution?  I did it once before.  I know I can solve it again.  Here’s what I’ve got so far just scrawling on some paper:

Step 1: Remove the luminosity.   I remember this clearly.  I remember in my first attempt at solving this years back, it took me a while to figure out that you really absolutely need to do this first and foremost, or else your colors will come out in all of the wrong shades.  This part is simple.  Given that red, green, and blue are input variables for your rgb color that you’re converting into an ryb system:


white = min(red, green, blue)
red -= white
green -= white
blue -= white

Now your rgb values contain no white value in them.  You’re working on converting pure color.  So you can take the next step, determining how much raw yellow there is, and how much of the green value is actually representative of the color green:


yellow_part = min(red, green) # In rgb red and green combine in equal parts to make yellow.  So we have to determine how much yellow there is.
green_part = max(0, green - yellow_part) # Now that we know how much yellow there is, we can take the raw yellow away from the green value to determine how much raw green is truly in the green value.

This next step I haven’t tested out yet.  I know that I’m not 100% certain that it’s a final solution because I know that at the very least I haven’t normalized the end values back into the proper scale.  What do I mean?  Well in an ryb system green is essentially yellow plus blue.  But we also have a blue value.  So in a worst-case scenario, we have a maximum blue value of 1/2 green plus blue.  In OpenGL where you’ve got a component scale of 1.0 maximum in rgb, this means blue could have a maximum value of 1.5 in ryb.  So you’ve got to re-scale the values after converting their components.  As I said, I don’t have that worked into the formula yet, but I do have part of the formula:


half_green = green_part / 2 # We know that green needs to be divided into equal parts of blue and yellow, so to optimize the code we calculate half of the remaining green component.
red = red - yellow_part
yellow = yellow_part + half_green
blue = blue + half_green

So at this point you should have the raw component color parts of a red, yellow, and blue color system.  Next up is normalizing the values back to the same scale as was used in the rgb system, and then putting the luminosity back in by re-adding the white value.  Do this and you should be done converting rgb to ryb.  Sometime when I get around to reinstalling Python + PyQt and/or some version of Visual Studio on my computer I may even get around to finishing the conversion code (and testing) in a follow-up Part 2 blog entry.