Wednesday, September 3, 2014

Is an "yellow" traffic light yellow?

Once common disagreement in my household is what color is the "slow down yellow" light between red and green (or in Utah the "speed up" light)?  I always said it was orange.  Some people call it amber.  Yellow is what the cop usually calls it as he or she is writing your ticket.   But since writing that glue/green post I have become very aware of teals around my environment and I swear the "green light" is teal.  A quick web search revealed that LEDs have not surprisingly taken over the traffic light industry, and every buying government has its own spec.  There probably is a converging standard, but my quick search didn't find it.  And these LED lights are probably NOT the same as what I've been looking at all these years.  So I took a picture near my house and by eye calibrated it so it looks "right" when at the scene.  Obviously not scientific, and just my streetlights. 

Here they are (note the awesome aliasing from the too many megapixels trend... ironic that video games can finally render wires but cameras finally can't!):


Blurring and grabbing the center of the blurred light yields:


I thought about mining the xkcd data to see what people call these and them and realized I was too lazy to do that.  But before giving up I made one last google and found this awesome visualization.  My read from that is pretty good names for the above colors are "turquoise",  "salmon", and "magenta".  Of course context is important, and as red, yellow, and green are highly salient primary colors so I think sticking with "green", "yellow", and "red" makes things less confusing.  And note how complex the interaction of names and colors can be, check out this discussion that leads with blue Japanese traffic lights.

Tuesday, September 2, 2014

Our "crazy" experiment for app discovery

With millions of apps out there, it's hard to get anyone to notice your app.   This "app discovery" problem is nicely summarized in this  Forbes article.  We learned with our app Fanpix that "if you build it they will come" is a non-starter no matter how broad the potential audience is.  We're big fans of Snapchat, but:
  • it doesn't map very well to some of our own use cases;
  • we wanted to emphasize privacy as much as possible;
  • we wanted stickers;
  • we wanted anonymous sharing to the Web.
So we developed our own social photograpy app, Pando.  Our central problem with Pando is of course app discovery.  We began with the depressing truth that if 0.1% of app developers are following a particular discovery strategy, that is one thousand developers, so it's still easy to get lost in the crowd.

Our basic assumption is that we need to do something different.   Because so many smart people are out there trying everything under the sun, our strategy either needs to involve something that is hard, or something that is seemingly stupid, or both. 

We did this: wrote a serious Windows Phone implementation

This does seem questionable considering the following data from idc: in 3Q  2013 Windows phones were only 3.6% of those purchased.  But it sounds better this way: in 3Q 2013, there were 3.7 million Windows phones sold.

iOS phones meanwhile sold 27 million phones in that quarter.    When you factor in degree of difficulty of getting discovered (Windows still only has a few hundred thousand apps), in which market is it easier to reach a million users?  So we think this strategy of emphasizing a Windows Phone version of our app is not stupid, just difficult.  It is difficult because the Windows Phone programming environment is completely different than the iOS or Android environments and we conservatively rejected the current portable wrappers on the three environments because a native implementation is always safe. 

In addition, Pando is a social app, so if we can penetrate the Windows market, it can then spread to their friends.   We like the Windows Phone strategy even better when we see the Windows Phone users are concentrated more in some countries than others, and in 24 countries Windows outsells iOS!   In Q3 2013 that article discusses several countries but the 16% sales share of Windows in Italy particularly caught our eye. 

One question that we had to answer before devoting resources to it,  is do Windows Phones suck?  I decided the only way to find out was to use one, which I have done for the last six months.   The Nokia/Windows combo I think is really super.  I like the phone a lot (more detail here).  The problem is lack of apps, but that just encourages us with our strategy.

Our conclusion is that if developing a social app you of course need iOS and Android, but best to spend the marketing budget on developing a Windows Phone app and get the app discovered there, where discovery is not yet crazy hard.  That is exactly what we have done with Pando, now available in beta form on iOS, Android, and WindowsMobile!

Here is a gratuitous screenshot of a selfie on my trustie Windows phone:




Monday, September 1, 2014

vec3 type in Swift

I am back to writing a ray tracer in Swift for my own education.  I just did a vec3 class.  My current practice is directions, locations, and RGB colors are all vec3.  This is mainly because I like that in glsl.  I'm going with Double because I am not trying to be very fast here for now.  Swift has nice syntax for this.  All lines from the file are here.    Any suggestions appreciated.  Next on the list is a class for ray-intersectable surfaces.

// implicit type inference.  Swift when in doubt assumes Double
struct vec3 {
    var x = 0.0, y = 0.0, z = 0.0
}

func * (left: Double, right: vec3) -> vec3 {
    return vec3(x: left * right.x, y: left * right.y, z: left * right.z)
}

func / (left: Double, right: vec3) -> vec3 {
    return vec3(x: left / right.x, y: left / right.y, z: left / right.z)
}

func * (left: vec3, right: Double) -> vec3 {
    return vec3(x: left.x * right, y: left.y * right, z: left.z * right)
}

func / (left: vec3, right: Double) -> vec3 {
    return vec3(x: left.x / right, y: left.y / right, z: left.z / right)
}

func + (left: vec3, right: vec3) -> vec3 {
    return vec3(x: left.x + right.x, y: left.y + right.y, z: left.z + right.z)
}

func - (left: vec3, right: vec3) -> vec3 {
    return vec3(x: left.x - right.x, y: left.y - right.y, z: left.z - right.z)
}

func * (left: vec3, right: vec3) -> vec3 {
    return vec3(x: left.x * right.x, y: left.y * right.y, z: left.z * right.z)
}

func / (left: vec3, right: vec3) -> vec3 {
    return vec3(x: left.x / right.x, y: left.y / right.y, z: left.z / right.z)
}

func max(v: vec3) -> Double {
    if v.x > v.y && v.x > v.z {
        return v.x
    }
    else if v.y > v.x && v.y > v.z {
        return v.y
    }
    else {
        return v.z
    }
}

func min(v: vec3) -> Double {
    if v.x < v.y && v.x < v.z {
        return v.x
    }
    else if v.y < v.x && v.y < v.z {
        return v.y
    }
    else {
        return v.z
    }
}

func dot (left: vec3, right: vec3) -> Double {
    return left.x * right.x + left.y * right.y + left.z * right.z
}

func cross (left: vec3, right: vec3) -> vec3 {
    return vec3(x: left.y * right.z - left.z * right.y, y: left.z * right.x - left.z * right.x, z: left.x * right.y - left.y * right.x)
}

Saturday, August 30, 2014

A tale of three phones

In an effort to understand the phone ecosystem better I gave my daughter my iPhone 5 over a year ago and bought a Samsung Galaxy S 3 running Android and used it for about six months.  I then tried a blue iPhone 5c under the mistaken impression it would be the success in Asia Apple hoped it would be.  After a couple of months I got the Nokia Lumia Icon which I have had for about half a year now.

While I do regret that I couldn't get the a phablet Android (not available on Verizon at the time), and I regret not getting an iPhone 5s (preferably the gold one), and I wanted the long optical path of the Nokia Lumia 920 (again not available on Verizon at the time), I did accomplish the goal of my experiment to get the experience of being a "real" user of iOS, Android, and Windows Mobile.  The hardware of all three particular devices was very impressive, although the iPhone 5c was not much different than my previous 5, and the Galaxy was already mature technology so lagging a little.

Pros:
  • iOS  The app ecosystem was very rich, and the look and feel was very smooth.
  • Android   The app ecosystem was almost as rich as iOS, and the interoperation of apps was neat.  The support for various google services was of course good.
  • Windows   Very smooth UI that was much better to use than I imagined given this is such a new piece of software.  On par with iOS in my subjective opinion.
Cons:
  • iOS  No google maps.  I actually got lost in Boston due to this and ended up in a sketchy neighborhood.  This has been fixed but shows the dark side of the curated closed environment.   Also, the thing is too small for my old eyes.
  • Android  Too much software and Samsung preloaded apps made things confusing.  This shows the dark side of open environments where specific hardware manufacturers sometimes have a negative incentive to support common portable environments between Android devices.
  • Windows   Too few apps.
What really surprised me is that I liked my Android experience the least.  This is personal taste, and I am very impressed with the new HTC phone a friend showed me so this is a dynamic issue, but I am really liking my Lumia running Windows.  Until Windows solves the app problem I am still going to buy Apple once it joins the 5" club, but I think Microsoft really scored with this OS.  Android was nice, but it is already starting to have the Balkanization problem we saw with Linux.  I would love to see google have a "standard" set of apps and settings I could download and get rid of as much manufacturer "improvements" as possible; with that I would give Android another try.  After all, the wild west of Android hardware is why we have phablets, so it does spur innovation.

Color names of the corners of the RGB cube

I've been spending a lot of time with the RGB cube lately and my biggest lesson has been that while it is mathematically very symmetrical between the primaries, it is not symmetrical subjectively (no, this is not a surprise to most of you).   The corners of the cube are key points when messing with it, and in order of increasing luminance (which is a confusing order and I use to emphasize don't get fooled by the geometric symmetry):
  • black (0, 0, 0) 
  • blue (0, 0, 1)
  • red (1, 0, 0)
  • magenta (1, 0, 1)
  • green (0, 1, 0)
  • cyan (0, 1, 1)
  • yellow (1, 1, 0)
  • white (1, 1, 1)
If we believe advocates of opponent process color theory (I am one of them and am in good company given DaVinci stated the opponent primaries were the right ones like it was not a matter of debate), the "true" primaries  are red, green, blue, yellow, black, white.   Your own experience with the names of the "mixed" corners gives some meat to that; which color name is more part of the human vocabulary:
  • cyan
  • magenta
  • yellow
 In fact look at them and try to quickly name them:
The xkcd survey shows that the subject population is more comfortable with the color association with the word "cyan" than it is with "magenta", as is shown from this figure from the survey:

I am impressed people know what "cyan" is; I don't think I would if I weren't in graphics.  I think "pink" is not a bad choice subjectively, but (255,128,128) is more of a classic pink (and note how far it is from the magenta vertex!).  Anthopologists have studied what are the "order" color is added to languages as the develop and an image on the excellent Wired article about Crayola's influence on color naming in the current world has this figure summarizing the anthro work:

There too cyan and magenta appear to be second-class RGB citizens.  Interesting also that yellow trumps blue, and that is consistent with the theory that the RG part of the vison system came first in evolution but I don't know enough to comment on that.

Bottom-line is do take advantage of the wonderfully simple math on the unit cube when using RGB, but always keep in the back of your mind that color as an experience is more complicated and less symmetrical.

Thursday, August 28, 2014

Designing our logo

I am unconvinced logos for software companies (as opposed to programs) really matter as long as one doesn't go too far away from lower case letters in a box.  But it's fun to mess with them, and you have to look at your own logo every day.  We had some criteria for ours:
  1. Not too many hues (I think 2 max is good)
  2. Not too oblong for web layout
  3. Meaningful about the company
  4. Geometrically simple
We went with the key figure from our original meeting when we decided to go with mobile photography apps.

Excuse the "we're the best": it was for internal consumption.  There are a million versions of this diagram on the web and I believe they have their root in Good To Great (2001) where the center of the diagram is "the hedgehog".  The diagram itself has all the four properties above so let's use that.  We just have to work out the details. 

For geometry let's nerd out and look for too much order.  The size of the center region varies with spacing and we like the centers to be in cool spots: the center of each can be where the other two circles intersect.




We like the teal color, but it is low color purity, and we'd like at least the center to have 100% purity.  So we just need to decide how the color combines.  We could do a physical transparency model, but photo-processing is all about abstraction, and a physical model wouldn't do that, so we instead go to pure teal in the middle with lower purity teal in the surrounds.  We add white lines to make it less boring.  We pick the orientation by feel.

And now the key thing: declare it "good enough" and go on to things that definitely matter.   We added the name of the company over the logo on the website because we didn't like how it looked beside it:


But I do have to wonder whether we missed a chance for free publicity with accidental logo features.

Wednesday, August 27, 2014

RGB Luminance revisited

One of the first things you learn in graphics is that green is subjectively brighter than red than is brighter than blue.  This goes back to the old school TV formula for converting color (RGB) to BW TV.  The wikipedia article on this is pretty good, and makes the important practical distinction between non-linear luma and linear luminace that all that gamma business.   But is getting that luminance formula important?  And if so, what is it for modern LCD screens?  I have had to pick a formula for my apps (I use an HSV inspired color space so need a formula for V) and it in practice doesn't seem to matter, but I thought I should dig into this a little now that the betas are done. 

First, always question all assumptions if easy to do so!  Are the primaries really different?  I find this question confusing: which of the colors below is brighter?

So we shouldn't expect an easy or clean answer here, and thinking there is an exact one is probably naive.  But that doesn't mean we shouldn't pick a standard if they are different.  To get at this I use a really cool indirect measure Gordon Kindlmann and collaborators used over a decade ago for designing pseudocolor maps.  See the paper for the roots of this idea.  I use the image from that paper with a few mods for easy photoshopping.  The basic idea is we see something as a face if light and dark are distributed "well".   It's faces and saturated colors and who knows what monitor you are looking at this on, so if you think this is science, you didn't read the disclaimer that is implicit here.

Here are images with all-on RGB (255, 0, 0), (0, 255, 0), (0, 0, 255), and black, white, and neutral grey (128, 128, 128).


Note some clearly look like faces, and some are more confusing.   Where the grey level crosses over so they are both confusing, the saturated color and the grey are about the same "brightness" under this measure.  Note with black, the right part of the pair always looks more natural, and the opposite with white.  If you look in the middle pairs, it does appear true that green is brighter than neutral grey, blue is darker, and red is more uncertain.  So the green > red > blue we always hear is still true.

Using my computer and my eye, here are the cross-over greys:
Cross-over greys are about 76/255, 128/255,  213/255.
This implies the primaries are very different.  For luma (not linear intensities)  and these 3 data points this implies

L = 0.29B + 0.5R +  0.83G

Those don't add up to one, so the non-linearities are in play for sure.   What if we assume gamma = 2.2, and then redo this.  Now the cross over points are: (0.07, 0.21, 0.66).   That's a lot closer to adding up to one, so more what we are used no in messing with linear gamma.  But is that a coincidence or is it useful?  Let's see if it is predictive.  What if we use pure magenta (255, 0, 255) and predict the cross-over.  If we use the luminance formula were we normalize the constants above to get to sum to 1.0:

L = 0.07B + 0.22R + 0.71G

We get for magenta 0.7+0.22 = 0.29.  If we gamma correct that at 2.2 and convert to 0..255 we get (147/255).  Trying it, before I knew this number, I got about 150 as my subjective crossover:
Greys 0, 128, 150, 255

So it looks like for this half-baked test, the luminance formula for sRGB is not far off:

L = 0.0722B + 0.2126R + 0.722G

Actually it's suspiciously close.  Either the sRGB standard is really making monitor calibration/standardization finally kind of happen, or I got lucky. 

Note that while this post was accidently a post endorsing doing gamma right, I actually believe that what matters in practice is not doing gamma wrong.  But doing it "right" is one way to make sure you don't do it wrong (thinking 128/255 is half as much physical intensity as 255/255).