Polyvore’s Image Masking (or someone I am really proud of)

before after

Cindy is a member of Polyvore’s awesome engineering team.  She just put up a post on our eng blog about how she improved Polyvore’s automatic image background removal tool. This level of attention to detail and polish has always made me proud. The change was part of a larger project to enhance the overall image quality on Polyvore and I hope she will get around to writing the entire series of posts.

Under the Hood: How we Mask our Images


Google Glass: Revolutionary but Not Quite Right

Google Glass is not visually symmetric.

Google Glass is revolutionary because it takes a big step away from the traditional screen + keyboard/mouse/touchscreen paradigm and towards a hands-free, always-on personal computing experience.

But it will most likely fail to gain mainstream adoption because of at least one simple reason: lack of visual symmetry.

Humans equate symmerty in faces to beauty.  That is why people usually wear facial jewelry like earrings in identical pairs.  Google Glass’s current design breaks that visual symmetry.  Every time I have encountered someone wearing one on the street, I have been thrown off — I can’t look the other person’s face without being completely focused on the display/camera module.  It is as if the other person had a huge, impossible to ignore, pimple on their forehead.  This is in contradiction with the goal of getting technology out of the way of natural interactions.

However, the next version might not have this flaw.

Update: I am not the only person with this idea.  Here are actual designer’s attempts at re-designing Google Glass.  All the  variations are symmetric: Bloomberg — Four Stylish Google Glass Re-Designs

iPhone 4S over 5

A hefty Bang & Olufsen remote control

I thought I was one of the few people who preferred iPhone 4S over 5 until an article in LA Times caught my eye:

So many consumers are opting to buy older iPhone models that some analysts wonder whether Apple has lost its ability to create new versions that dazzle.

I am not the type to stand in lines to be the first to get my hands on a new device. The arrival of iPhone 5 was no different, I waited a few weeks until the hooha around it had died down before heading over to a local Apple Store.  I had been using my two year old iPhone 4 with a broken glass and thought it was finally a good time to upgrade.  But when I picked up an iPhone 5, it felt like it was made of cheap plastic — it was strangely light.  I am quite fond of the feel of the iPhone 4, so instead I replaced my broken (actually bent) old phone with a new 4S.

iPhone 5’s lack of heft reminded me of this passage from John Maeda’s Laws of Simplicity:

Sometimes mixing actual and perceived qualities works well, like in the design of the Bang & Olufsen remote control.  The unit is thin and slender in composition and made with the finest materials, but is significantly (and intentionally) heavier–as a means to subtly communicate higher quality–than you would expect from its appearance.

I have always appreciated Apple products not only for their software but also for the high quality of their hardware.  And I am sure Apple’s design team pays close attention to details like the perceived weight of the device.  The latest iPhone somehow managed to defy both expectations.

New vs better

Sharpening our focus – to bring you new Yahoo! products

With all due respect, that sentence should read:

Sharpening our focus – to bring you better Yahoo! products

Wish: SUB-INSERT SQL statements

Sub-selects are nice:

 (name, phone, city_id)
   (SELECT id FROM city WHERE name = 'Los Angeles')

It saves a DB roundtrip to find the city.id for ‘Los Angeles’.

But sometimes you encounter a new city and first have to assign an entry for it in the city table. Except that the row may already exist, so first you have to select the city, if it does not exist, create the city and finally store the person. MySQL has a nice pattern for storing rows that might already exist in the DB, allowing us to combine the select-if-not-found-store steps into one:

  ('Palo Alto')

MySQL will return the correct city.id for the new city entry regardless of whether the row had to be inserted or it already existed.

Now, it would be sweet if INSERTs could be used the same way SUB-SELECTs are, allowing us to combine all three steps into a single statement:

 (name, phone, city_id)
     INSERT INTO city
      ('Palo Alto')
      UPDATE id = LAST_INSERT_ID(id);

This pattern happens all the time when storing complex records that span multiple tables. It would be very convenient if databases would support it natively.

Warehouse Robotics + Data Centers

Inspired by: The Building is the New Server by @w_scottweiss + Faster Than Overnight by @MarcusWohlsen + Amazon buys Kiva Systems

Our future overlords Google, Amazon, Apple, Facebook,… are all building new massive datacenters. Servers are custom designed for maximizing density, and ease of replacing failed components.

The next logical step is datacenters built similar to modern warehouses used by the likes of Amazon for order fulfillment. Modern warehouses are designed to allow robots to stock and retrieve all the goods from shelves. These warehouses acheive far higher efficiency and density than those operated by humans. Because of the structured nature of datacenters (racks upon rack of servers) robots could be similarly adapted to replace failed components, servers, etc… in datacenters. Designing with robots in mind might enable entirely new layouts, topologies and environments for increased density and cooling performance.

Wish: Retina Display Image Magnification Service

I am writing this on a Retina MacBook Pro. Text and anything rendered from vectors looks absolutely, I’ll-have-a-hard-time-going-back-to-non-retina, amazing. But poorly scaled bitmap graphics look terrible. The contrast between the ultra crisp text and the pixelated, fuzzy scaled graphics makes the problem even more glaring and annoying.

For Polyvore’s Mobile HTML site, we had to deal with this problem. We switch to serving 2x dpi images when the client device uses a high dpi display. We could easily do this because our backend image rendering pipeline is able to render generate images in different resolutions.

But what about all our other image assets? And what about all the other services out there that can’t serve high dpi versions of their images?

A useful service would be some kind of Image Scaling proxy that sits in from of your image servers and dynamically decides what kind of image resolution it should serve.

If you have high resolution image sources, serving lower resolution images is not a problem. There are lots of algorithms that can down-scale images and produce great looking output.

The problem is when you have to magnify images from standard resolution sources. For pixel art type image, there are algorithms like hqnx.

NN interpolation

hqnx scaling

For photos and images of natural things, there are good magnification algorithms like fractal based scaling.

Fractal Resizing

But there is another class of hard-to-algorithmically-magnify images. Things like icons with gradients, a mixture of pixel art and natural images. For these, it would be interesting to offer an automated best-effort option but also create a marketplace where graphic designer can redo your image assets in high resolution. The proxy server would use the best option available to it.

imgix seems to be headed in this direction. Services like CloudFlare, Strange Loop and InStart could also offer this type of service.

No Hack Days at Polyvore

Do Whatever You Want Week

Instead we have: Do Whatever You Want Weeks.

Hack Days are in theory a great idea — let people who otherwise don’t get a chance to quickly prototype projects, showcase their ideas or plain work on something other than their usual work load.

But there are a few problems:

  • A single day is often not enough for realizing a serious idea.
  • People tend to work on whiz-bangy projects that are easy to demo but not very useful.
  • Sometimes, what people need most is not the variety of working on a new project but a complete break from programming.

To fix these problems in our version of Hack Days we created Do Whatever You Want Weeks.

DWYWW’s are exactly what the name suggests — a week of doing whatever you want. We chose a week because we felt it was enough time to get something serious done. People can do literally whatever they want — if someone feels what they need most is a week off, they can take it, no strings attached. If they want to code all week, they can do that too.

In practice, we work at a reasonable pace on stuff we really care about. We work on refactoring code, fixing bugs, mocking up new designs and of course creating new features that our community loves.

In some ways, DWYWW’s are not very different than our regular work weeks. And that is the point. Great companies shouldn’t really need Hack Days to let their staff work on cool stuff, they create an environment where it can happen every day.

Great Office Work Environments

Note: This is based on a answer to a question about what makes for a good office space on Quora

At Polyvore we made our fair share of mistakes but the office work environment is one of the things we mostly got right.

Polyvore Office

Lots and lots of plants being installed at our office

When we were starting out, I knew that we’d be spending most of our waking hours there for the foreseeable future and we wanted to make our work environment as great as possible.

Our guiding principle has been that great people deserve to work in a great environment.

Here is a partial list of what we did:

Office Building
  • Modern building
  • Look out the window and you see trees
  • Within walking distance of downtown and train station
  • Lots of natural light
  • Warm toned interior lighting — not the fridge like cold fluorescent.
  • High ceilings
  • High quality desks / seats
  • Lots and lots of plants
  • Ample space for everyone — not like a sardine can
  • Open layout — although there are people who prefer offices
  • A general policy of you can get whatever you need to best do your job
  • X-Large monitors
  • Latest/fast hardware — I hated how Yahoo laptops took 15 minutes to boot up
  • MiFi dongles for commuters
  • Dedicated IT staff to make sure everything just works
Benefits / Perks
  • Better than most startups Health benefits,…
  • CalTrain Go passes
  • Gogo inflight passes
  • Health and fitness allowance
  • Free home cooked catered lunch everyday
  • Organic fruits + snacks + drinks, …
  • Chocolate deliveries from The Chocolate Garage

I am probably missing some things. You can read more about it at Polyvore’s About Page.

There is of course the even more important human interactions element which is the topic of entirely different posts / threads / books.

Credit Rolls for Software

Software should have credit rolls the way films do.

At the end of every film, there are the credit rolls that acknowledge the work of everyone who was involved in the making of the film:

Star Wars Episode IV Credit Roll

Why not the same for software? In the case of films, all sorts of people get credit for their contributions but in most software and software services, we don’t know the contributors and usually we can’t even find out. I use tons of online services but I have no idea who the true contributors really are. At most, if the service is very popular, I might know the name of the founders (Larry/Sergey, Jerry/David, Adam D’Angelo, …).

This opacity is a huge shame because people who write software should rightfully be recognized for their work.

It is even technically possible to produce a credit roll for the software that we use. Here is a version control log (svn -blame) of who the latest contributor for each line of code for a Polyvore js function:

  8358      kwyee // Monitor calls f every interval ms.  
  8358      kwyee // It fires a change event when f() changes.
  8482      kwyee // f() is passed to the trigger event handler.
  2073      pasha function Monitor(f, interval) {
  2623      pasha     var curr = f();
  2073      pasha     if (!interval) { interval = 100; }
  8656      kwyee     this.check = function() {
  2073      pasha         var now = f();
  2073      pasha         if (now != curr) {
  2073      pasha             curr = now;
  2073      pasha             Event.trigger(this, 'change', curr);
  2073      pasha         }
  8656      kwyee         return now;
  8656      kwyee     };
 17189      pasha     this.timer = new Interval(interval, this.check, this);
  2073      pasha }

It is possible to take this information and instrument the code such that each execution keeps track of all the people who contributed and produce an exhaustive credit roll of sorts. There could be a dialog that shows all the people whose code was executed to make this app / page / REST call etc… possible. I actually remember that old System 7 era Apple software used to have credits in the ‘About X…’ dialogs.