Stereotypes

Every stereotype is true. How else did it become a stereotype?

The mistake we make as humans is overgeneralizing. We assume that because a stereotype is true much of the time, it should be true all of the time. Then we abuse the inevitable exceptions.

Stereotypes are useful and necessary for helping us organize our world. Let’s just avoid beating the exceptions into a mold.

Worst. Ad. Trend.

Levi’s “Real. Comfortable. Jeans.” ad campaign started a firestorm of copycats. Unfortunately, a huge number of these copycats don’t seem to understand the basic semantics of the English language that made Levi’s ad work.

See, the trick to Levi’s ad is that any combination of the words works as a stand-alone statement.

In the context of jeans:

  • Real.  -OK, I get it. Their jeans are the real thing.
  • Comfortable. -Got it. Their jeans are comfortable.
  • Jeans. -A little redundant with “Real”, but I get it. Their jeans are the real thing.
  • Real Comfortable. -Wow. Not just comfortable, REAL comfortable.
  • Comfortable jeans. -Kind of a bland statement, but it still make sense.
  • Real Jeans. -OKOK I get it. Your jeans are THE jeans.
  • Real Comfortable Jeans. -Now we get the whole banana. 

Every one of the above statements makes sense. Now examine one of the copycats:

Vertigo is a web development firm that, by all accounts, is quite good at what they do. I can’t say the same for the advertising firm that cam up with their “Best. Web. Ever.” promotion. Let’s do the same analysis as above.

In the context of a web site:

  • Best. -OK. You make the best web sites. Got it.
  • Web. -Yeah, I know you make web sites, but this still makes sense.
  • Ever. -Um. What? Here the formula breaks down.
  • Best Web. -Again, you make the best web sites. Got it.
  • Web Ever. -What?? This conjures up images of an ad designer who fell asleep at his/her desk and drooled all over the proposal.
  • Best Ever. -Optimistic, but still intelligible. I get it.
  • Best Web Ever. -Again, we get the whole picture. Got it.

And therein lies the problem that droves of copycat advertisers just don’t seem to get. Of the plethora of ads using this tactic, I have only seen one besides Levi’s that does it right.

I’ve seen ad ideas beaten to death (got milk/candy/air/body-odor/fill-in-the-blank? comes to mind), but few done as badly as this trend.

All you advertisers, please take a refresher course in English grammar. And - I know this is going out on a limb - how about you create your own ads instead of copycatting?

Dealing with predictors when decoding PDFs

I’ve seen a lot of questions about how to “unpredict” PDF Xref streams. The answer usually goes something like “RTFM!”

Well, I have R’d the FM, and it’s still confusing. So, to save others the pain I’ve gone through, here’s a slightly more detailed rundown.

A great blog explaining how PNG prediction works (which, yes, can be applied to text) is here:

http://www.atalasoft.com/cs/blogs/rickm/archive/2008/05/02/using-png-predictors- to-enhance-gzip-pkzip-flate-compression.aspx

A fun fact not covered in the blog: PNG prediction happens bottom-up, so when you decode you need to run your algorithm top-down.

Basic steps:
Assuming you’ve already decoded (inflated, un-gzipped or whatever) the string…

You’ll need to know the predictor type and the column width, at a bare minimum. This is provided in the Xref stream dictionary.

  • Predictor type will be “/Predictor” in the “/DecodeParms” subdictionary. Usually this is 12 (PNG Up prediction)
  • Column width will be “/W”. Usually this is [1 2 1]

Armed with this information:

  1. Strip off the last 10 characters of the string. This is the CRC and is unnecessary to extract the raw data.
  2. Sum up the column widths. For the example above [1 2 1] would be 4. This is one less than the number of bytes in each row.
  3. Split the string into rows by the column width: sum+1, or in our example, 5.
  4. The first byte on the row will be the predictor type. You can actually change the predictor line-by-line, though I haven’t seen an example of this actually happening. For PNG Up prediction (12, as above), the first byte should be 0×02. You should strip this off (i.e. assume all lines use the same prediction). If the predictor were 15 (optimized prediction), you’d need to write code to change the algorithm based on this number. Since we’re only considering 12 (Up prediction), we should be able to strip it off.
  5. You should now have a row equal to the <width> bytes (4 in our example). You now convert the row byte-by-byte. Since PNG Up unprediction works top-down, the first row is already effectively decoded. I create a “prevRow” array with <width> rows, filled with zeroes.
  6. Loop through each row, and within that loop loop through each byte in the row. Convert the byte from binary to int and add it to the same byte in the previous row. Pseudocode: unpredictedByte = prevRow[currentByte] + row[currentByte]
  7. Convert the int back to binary (actually, hex in PHP). You’ll see why in a second.
  8. Once you have all your rows unpredicted, loop through them again, splitting them into binary strings based on the W parameter. In our example: 1 2 1. I.e. the first string is 1 byte, the second string is 2 bytes, the third string is 1 byte.
  9. Convert the ENTIRE STRING to int (this is why we had to go back to binary, since the strings can be of arbitrary length).
  10. Your first column should be the Xref entry type: 0 = f. I.e. a “free” or deleted object. I typically  ignore these. 1 = n. I.e. an “in use” object. You’ll want to save these for the future. 2 = a compressed object. You’ll also want to save these, but they’ll require a little more work before they’re usable.
  11. If our first column is 1 (an in-use object), the second column is the offset address for that object. I add it to my Xref table array.
  12. If our first column is 2 (a compressed object), you have to decompress the object stream to get the actual object references and offsets. See PDF Specification section 7.5.7 (page 45).

 

The code in PHP looks like this:

$prevRow = array_fill(0, $totalWidth, 0); //Treat prevRow as an array of ints for math
for($j=0; $j<count($rows); $j++) {
$row = substr($rows[$j], 1); //Chop off the filter-type byte (should be 02 for UP prediction)
$offsets[$j] = ”;

//Reconstruct the string character by character
for($i=0; $i<strlen($row); $i++) {
$decodedByte = ord($row[$i]); //Convert the binary character to an int so we can do math on it
$decodedByte = $decodedByte+$prevRow[$i]; //Add the current row’s character to the previous row’s character
$decodedByte = $decodedByte & 0xFF; //Seems pointless to me, but Zend Framework does this
$prevRow[$i] = $decodedByte; //Update for our next pass

//WARNING: Assumes 1 2 1 column structure.
if($i == 0)
$types[$j] = $decodedByte;
else if($i == 1 || $i == 2)
$offsets[$j] .= chr($decodedByte); //Convert back to binary
if($i == 3)
$generations[$j] = $decodedByte;
} //Close for $i
}//Close for $j

Iran defiant at UN sanctions move

Iran defiant at Sanctions. North Korea threatening war if it is sanctioned.

Have sanctions ever worked?

It seems to me that the average despot isn’t going to be affected by sanctions. Say we sanction food. Joe Despot is going to take all the best for himself and let the rest trickle down to the populace once he’s had his fill. Sanction fuel? Joe Despot’s private jet is still going to fly him wherever he wants in air conditioned comfort while the common people have gas rationed and can’t get to work. If we sanction a country, we’re not hurting Joe Despot, we’re hurting the common folk.

Sanctions are supposed to be more humane than war, but it seems to me that it’s really a choice between bombing the common folk and starving them.

Police unable to stop killing rampage

June 2nd, 2010 one Derrick Bird of the UK reportedly went on a killing spree, killing his brother first, and then driving 45 miles, shooting randomly from his car and killing 12 people.

Doubtlessly, gun opponents and those who buy into a culture of victimhood will say this is another example of why guns should be restricted and we should leave defense to the professionals.

However, I’d like to point out the measures the professionals took: “42 armed officers were deployed” and “police and RAF helicopters were drafted into the area.” Even with this tremendous show of force, they were unable to apprehend Bird before he committed suicide.

I have to ask: what if his brother had been armed? What if one or several people at the taxi rank were armed? If the citizens on the ground had been empowered to defend themselves, might this tragedy have been much smaller or avoided completely?

This is a colossal  failure on the part of “the professionals,” and one more example why we are each ultimately responsible for our own defense: so we can be safe until the professionals are available.

Mixed Messages from Law Enforcement

There have been a handful of reports recently about women defending themselves against attackers. Unfortunately, far from applauding these women and thanking them for their help in bringing a criminal to justice, law enforcement professionals seem to be encouraging a culture of victimhood.

On May 5, 2010, a female college student was being attacked by a man with a knife. 5 other female college students saw the attack, and overpowered the attacker.

Police Sgt. Paul Edwards told the Bangor Daily News, “We would never recommend getting involved to the point where you might get hurt yourself and become a second victim.”

This flies directly in the face of discussions concerning making it illegal to walk by a crime in progress. Sgt. Edwards is promoting selfishness over self-sacrifice, and callously allowing others to become victims. So much for serve (others) and protect (others). Sgt. Edwards seems to be promoting “serve yourself and protect yourself.”

At least Sgt. Edwards had the decency to add, “But am I proud of what they did? Of course I am. Am I glad they did it? Yeah. I’m happy because the outcome was good.”

Australian law enforcement apparently didn’t even have that decency, when they were quoted as saying “not that we encourage that sort of thing” when a female Karate black belt defended herself against a would-be assailant.

If law enforcement officials would prefer we leave our defense “to the professionals,” I’d also like to point out that the woman attacked in Bangor, Maine had a restraining order against her assailant. Where were the professionals when he violated that piece of paper and came at her with a knife? If civilian passers-by had not intervened, this would probably be a murder case instead of assault. The professionals simply weren’t there.

Modern society, apparently including law enforcement professionals, need to recognize that self defense is a fundamental right and responsibility of every person. Unless police are going to take up 50% of the population and assign a professional bodyguard to every person, it’s impossible for them to be there to defend someone at the critical moment. Even a 5-7 minute response time may be too late.

I call on our government officials, especially those directly tied to law enforcement, to promote a culture of personal responsibility and self defense. Should we rely on the professionals whenever possible? Definitely. They have more training and a better knowledge of the law than we do. On the other hand, we all need to take responsibility for our own defense until a professional is available.

John and Alec

Why does “Alec” get to be “smart” while “John” is associated with undergarments and bodily functions?

PETA Euthanasia Rates

According to recent reports by AOL and Newsweek (among others), People for the Ethical Treatment of Animals (PETA) actually kills 80% - 90% of the animals brought to them for “rescue”, a much higher percantage than organizations like the SPCA.

Add to that their controversial “I’d rather go naked than wear fur” campaign and letters to the military requesting they not harm animals during fighting (nevermind the soldiers), it seems clear PETA is more about political hype than making a difference.

Perhaps they should be called “People Entertained by Terminating Animals.”

The Value of Tedium

Almost every article I read about web development these days whines about how “tedious” it is to write HTML. Many offer their own solutions, usually in the form of a customized language that offers a shortcut or two but is otherwise nearly as inane and tedious as they accuse HTML of being.

Personally, I like writing HTML. My job as a web report developer constantly involves thinking outside the box and coming up with creative ways to represent mountains of data in a succinct, easy-to-digest form. Coming back to something as absurdly simple and familiar as HTML is relaxing and comforting.

I think every job needs its share of tedium. If it was all bleeding edge creativity all the time, the crispy remains of our brains would try to escape out our ears within a few short months. A healthy balance of engaging creativity and “tedious” down time in the form of familiar or repetitive tasks strikes me as the ideal. Too much intensity and you burn out; too much tedium, and your hands go through the motions while your eyes unfocus and you drool on your best shirt.

So, I say bring on the HTML <insert your job’s tedious task here>. But not too much.

Pricing on your Website

In the February 2010 issue of Website Magazine, Michelle Kissinger argues that putting pricing on your web site may be counter productive (p. 39). She says:

“Your target market may not expect pricing independent of an offline interaction with your company. If this is the case, and your competitors are not exposing their pricing online, it would put you at a competitive disadvantage to break ranks - it might give users the impression that you are placing cost ahead of quality.”

I completely disagree. Speaking for myself as a consumer, I have a rule for myself: “If the price isn’t marked, it’s too expensive.” In other words, if pricing information isn’t readily available, I walk away. The few stats I’ve seen on the subject indicate that, while I’m in the minority, there are nonetheless a good number of others out there like me. Therefore, failing to put pricing information on your site could be losing you customers.

Now, admittedly, I’m one of those consumers the retailers dis-affectionately refer to as a “bottom feeder.” That is, I have no brand loyalty, I research my purchases before making them, and purchase the item that is the best compromise between price and quality when I’m ready to buy. This tendency has led to some awkward moments when companies force me to contact them before disclosing pricing information. The salesperson is chatting away, expecting a sale, until they finally mention the price and I say I’m not interested. In one case, the company insisted upon making an appointment and sending someone in person to meet me, only to have them turned away in five minutes because our opinions of an appropriate price were so wildly different. What a waste of time and company resources! It could have been avoided if they’d simply made pricing available on their web site.

I can think of one notable exception to this rule: customized products. If there is a product you need that requires a fair amount of customization, there is really no way to put standard pricing on your web site. There is no “standard” product, so “standard” pricing becomes meaningless. In all other cases, though, I believe posting competitive pricing is beneficial.