Archives:

« January, 2012 »
SuMoTuWeThFrSa
1234567
891011121314
15161718192021
22232425262728
293031 

Categories:

As the new year approaches, I've been reflecting on life.

Every once in a great while I get in this mood where I feel like I've been bottling up creativity and it's ready to explode. The only problem is, I have no idea where or how to direct that energy. As much as I want to be a part of some meaningful project, I feel stuck and often end up juggling several side projects unable to decide which deserves more precedence.

Once upon a time I decided I wanted to learn how to build my own website. I taught myself HTML and thought I was god. After a reality check, I decided to give Perl a try, gave up and started reading about C before a friend, Douglas Tyler, turned me on to PHP and I was hooked. I soon joined the online community codewalkers.com where I was quickly promoted to a moderator. As a thanks for my dedication and involvement, the owner at the time, Matt Wade, decided on a complete whim that he would ask for donations and send me to the first ever PHP Architect conference which took place on a cruise ship in the Bahamas. The cruise was an interesting experience, but not exactly a life-changing one as I thought it might be. Everyone was very warm and welcoming, but I couldn't help but ask myself what I was doing there. I was certainly no seasoned professional like the rest of them, just some punk kid who was lucky to be there. The trip lead to a few small contract jobs with PHP Architect, and another conference in Chicago 3 years later, but nothing more.

While writing book reviews on codewalkers, I was contacted by someone from Sams Publishing (Pearson Education) who asked me if I'd like to be a technical editor for an upcoming release which I of course accepted. That eventually lead to me authoring my first book through Sams. One of the ladies I met through Sams ended up leaving to go work for another publisher who had recently acquired the Wrox series, which lead to yet another book that I co-authored. It would seem I was on the road to success, but I still didn't feel like I was going anywhere.

In 2009, I got married. My wife is a Japan native, so between the cost and time of traveling back and forth to meet her family, I ended up taking a break from web development and settled for full time unrelated work at a local hospital. She is still struggling with English, doesn't drive, and there is zero Japanese community in the area where we live so I am the sole support and we are financially stressed out of our minds. I've been attempting to learn Japanese, but without the possibility of immersion it is extremely slow going. So here we are now, no idea where we will end up or if we'll even stay together, and I'm trying to get my feet wet in web development once again.

Through yet another friend from my codewalker days, Timothy Boronczyk, I've been writing for PHPMaster which is an awesome gig, but it pretty much just helps me get to my next paycheck. I'm not complaining; I enjoy the work, but it's only a part time thing.

I've applied for countless jobs, locally, out of state and even international, but nothing ever seems to pan out. I know I'm not alone as the world economy is in flux, and I suppose it doesn't help that I still don't have a clue what I want to do with my life career wise. I know that I love development, but I don't care at all for the commercialism that seems to dominate the field. I want to work on a project that is doing something educational and not just trying to make a sale. I want to take my time writing code that is new rather than hacking a bunch of libraries together to get it done fast.

I keep jumping all over the place and I feel obligated to give back to the community that has treated me so well. If I could just focus my energy on something specific, but what that something is eludes me. It feels more like I'm waiting than anything else. Waiting for what... Another year? I still feel like I'm that punk kid just lucky to be here.

December 24 2011, 5:40 pm
Misc : Comments (4)

Spam me if you can

Ever since I've had a few of my blogs linked to on other more popular websites, namely phpdeveloper.org, I've been getting a fair share of comment spam. I was just banning IPs which worked okay up until tonight. I haven't been able to sleep because my phone keeps dinging with a new comment notification every 20 minutes or so from a dynamic IP. I'm not losing sleep because of frustration, but rather the fact that I love a good challenge and my brain can't shut down while the wheels are turning.

My comments are setup to be non-intrusive on purpose. I welcome those who wish to remain anonymous; I certainly can't expect anyone to register an account for my personal (who the hell is this guy?) blog. I don't like CAPTCHA images or similar measures of spam prevention because it forces visitors to jump through hoops for what should be my problem. I'm the one being attacked, and there really is no excuse to make my site less user-friendly just because I'm too lazy to sift through a little spam.

After studying my bots behavior I noticed something curious... It always fills out optional fields. That makes a lot of sense, actually. Why would a bot designed to crawl the web and spam different websites bother to check if certain fields are required or not? That would be hit and miss, especially when you consider that a lot of websites don't even make it clear which fields are required until you click the submit button.

In order to confirm my hypothesis, I added a completely arbitrary field to my comment form, set the display to hidden so no human beings see it, and sure enough the bot is still filling it out. Spam avoided. Additionally, I proceed to display a "success" message just so they don't have any reason to probe further.

I'm sure it isn't fool proof, but I could further expand it to generate random arbitrary fields and hide them using different methods. I can't imagine why a spammer would go out of their way to target my website specifically, and modifying their bot to recognize required fields might just be more trouble than it's worth?

We shall see, shan't we. Your move, spammer.

November 12 2011, 4:35 am
Web Dev : Comments (2)

CSS child combinator

I recently stumbled across the CSS > child combinator, something that has been around since CSS2 but for whatever reason I never bothered to give it any attention. The w3c describes it as representing a parent / child relationship, but what exactly does that mean? While X Y will effect every Y child of X, X > Y will only effect direct children. I was pleasantly surprised to discover just how useful this can be.

When using the combinator to create a child selector we can, for example, create a pure CSS drop menu with unlimited sub-menus. I've thrown together two examples below.

Vertical Menu:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head><title>Vertical Menu Test</title>
<style>
#menu {
  float: left;
  margin: 0px;
  padding: 0px;
}

#drop {
  margin: 0px;
  padding: 0px;
  height: 20px;
}
#drop li {
  list-style-type: none;
}
#drop li a {
  display: block;
  width: 160px;
  border-top: solid 1px #FFF;
  padding: 5px;
  background-color: #000;
  color: #FFF;
  text-decoration: none;
}
#drop li:hover > ul {
  display: block;
  position: absolute;
  border-left: solid 1px #FFF;
  margin-left: 170px;
  margin-top: -30px;
  padding: 0px;
}
#drop li:hover li, #drop ul li {
  float: none;
}
#drop li:hover li a {
  background-color: #000;
  color: #FFF;
  opacity: 0.8;
}
#drop li li a:hover {
  background-color: #CCC;
  color: #000;
}
#drop ul {
  display: none;
}
</style>
</head>
<body>

<div id="menu">
<ul id="drop">
  <li><a href="#">Main 1 &#155;</a>
  <ul>
    <li><a href="#">Sub 1.1</a></li>
    <li><a href="#">Sub 1.2</a></li>
    <li><a href="#">Sub 1.3</a></li>
  </ul></li>
  <li><a href="#">Main 2 &#155;</a>
  <ul>
    <li><a href="#">Sub 2.1</a></li>
  </ul></li>
  <li><a href="#">Main 3</a></li>
  <li><a href="#">Main 4 &#155;</a>
  <ul>
    <li><a href="#">Sub 4.1 &#155;</a>
    <ul>
      <li><a href="#">Sub 4.1.1</a></li>
      <li><a href="#">Sub 4.1.2 &#155;</a>
      <ul>
        <li><a href="#">Sub 4.1.2.1</a>
      </ul></li>
    </ul></li>
    <li><a href="#">Sub 4.2</a></li>
    <li><a href="#">Sub 4.3</a></li>
    <li><a href="#">Sub 4.4</a></li>
  </ul></li>
</ul>
</div>

</body>
</html>


Horizontal Menu:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head><title>Horizontal Menu Test</title>
<style>
#menu {
  width: 750px;
  margin: 0 auto;
  padding: 0px;
}

#drop {
  margin: 0px;
  padding: 0px;
  height: 20px;
}
#drop li {
  list-style-type: none;
  float: left;
}
#drop li a {
  display: block;
  width: 160px;
  border-top: solid 1px #FFF;
  border-left: solid 1px #FFF;
  padding: 5px;
  background-color: #000;
  color: #FFF;
  text-decoration: none;
}
#drop li:hover > ul {
  display: block;
  position: absolute;
  margin: 0px;
  padding: 0px;
}
#drop li:hover > ul ul {
  margin-left: 171px;
  margin-top: -30px;
}
#drop li:hover li, #drop ul li {
  float: none;
}
#drop li:hover li a {
  background-color: #000;
  color: #FFF;
  opacity: 0.8;
}
#drop li li a:hover {
  background-color: #CCC;
  color: #000;
}
#drop ul {
  display: none;
}
</style>
</head>
<body>

<div id="menu">
<ul id="drop">
  <li><a href="#">Main 1 &#155;</a>
  <ul>
    <li><a href="#">Sub 1.1</a></li>
    <li><a href="#">Sub 1.2</a></li>
    <li><a href="#">Sub 1.3</a></li>
  </ul></li>
  <li><a href="#">Main 2 &#155;</a>
  <ul>
    <li><a href="#">Sub 2.1</a></li>
  </ul></li>
  <li><a href="#">Main 3</a></li>
  <li><a href="#">Main 4 &#155;</a>
  <ul>
    <li><a href="#">Sub 4.1 &#155;</a>
    <ul>
      <li><a href="#">Sub 4.1.1</a></li>
      <li><a href="#">Sub 4.1.2 &#155;</a>
      <ul>
        <li><a href="#">Sub 4.1.2.1</a>
      </ul></li>
    </ul></li>
    <li><a href="#">Sub 4.2</a></li>
    <li><a href="#">Sub 4.3</a></li>
    <li><a href="#">Sub 4.4</a></li>
  </ul></li>
</ul>
</div>

</body>
</html>

In the vertical example, the magic happens in the block li:hover > ul. This instructs the browser to display any ul that is a direct child of the li element being hovered, and any sub-ul will remain hidden until its parent is hovered. In the horizontal example, there is an added block li:hover > ul ul. The second block is needed because the ul tags are being displayed two different ways: vertically from the main menu, and horizontally for each additional menu. To add more menu items, one simply needs edit the bulleted list tags. No javascript, no browser hacks (IE6 excluded), no limits!

It's funny how something several years old can get me so excited. I can't help but wonder what other potential headache savers I've been missing out on.

October 22 2011, 11:44 am
Web Dev : Comments (2)

Back from Japan

ff0865714ff43a33684802d756fa86039cd556ed.jpg
1 of 19
I just returned from my third trip to Japan, this time for my brother-in-law's wedding party. I've attached a few of the pictures I took including a few souvenirs.

The wedding was interesting, not too far off from an American style ceremony with a few exceptions. To name a few, in America the brides family traditionally pays whereas in Japan it's the mans family; every visitor both gives and receives gifts; and instead of dancing they have karaoke. I didn't even realize when I took the picture that the women were all bowing lower than the men. The wedding was held at Haneda airport which is still fairly new. It began with family introductions, then pictures, then a five course meal where friends joined in with speeches, tears and gifts. Then we met for a family-only after party with more food and lots of drinking. I'll never cease to be amused at how long it takes Japanese people to say goodbye, even if they'll see each other again the following morning.

While I have no affiliation with Caterpillar, it was neat to see one of their tractors in action since the company has somewhat of a big presence in my home town. They're still working to repair the streets and uneven pavement from earthquake damage. We ended the trip with some purikura pictures and sushi at an always busy restaurant.

I wish I could say it's good to be home, but it feels more like I just left.

October 11 2011, 9:17 pm
Misc : Comments (0)

Watermarking with text and ImageMagick

In my most recent venture with PHPMaster I was asked to write an article about watermarking images with PHP using ImageMagick. Virtually no documentation exists on the PHP API, although there are plenty of command-line examples from the official ImageMagick website.

I spent a solid day and a half attempting to convert command-line code into PHP before (due to miscommunication) the topic was covered by someone else and my work was no longer needed. Although disappointed, it gave me something to blog about! Yay.

I was able to complete 3 basic examples which are outlined below. First, here is the original image of some handsome looking guy:



Drawing text on the image
Code:
<?php

// Create objects
$image = new Imagick('mug.png');

// Watermark text
$text = 'Copyright';

// Create a new drawing palette
$draw = new ImagickDraw();

// Set font properties
$draw->setFont('Bookman-Demi');
$draw->setFontSize(20);
$draw->setFillColor('black');

// Position text at the bottom-right of the image
$draw->setGravity(Imagick::GRAVITY_SOUTHEAST);

// Draw text on the image
$image->annotateImage($draw, 10, 12, 0, $text);

// Draw text again slightly offset with a different color
$draw->setFillColor('white');
$image->annotateImage($draw, 11, 11, 0, $text);

// Set output image format
$image->setImageFormat('png');

// Output the new image
header('Content-type: image/png');
echo $image;

?>

Result:


This example is pretty straight-forward and with the comments shouldn't need much explanation. While it works, the font is too bold and stands out too well from the image. Typically a watermark should be more subtle.

Draw transparent text using a font mask
Code:
<?php

// Create objects
$image = new Imagick('mug.png');
$watermark = new Imagick();
$mask = new Imagick();
$draw = new ImagickDraw();

// Define dimensions
$width = $image->getImageWidth();
$height = $image->getImageHeight();

// Create some palettes
$watermark->newImage($width, $height, new ImagickPixel('grey30'));
$mask->newImage($width, $height, new ImagickPixel('black'));

// Watermark text
$text = 'Copyright';

// Set font properties
$draw->setFont('Bookman-Demi');
$draw->setFontSize(20);
$draw->setFillColor('grey70');

// Position text
$draw->setGravity(Imagick::GRAVITY_SOUTHEAST);

// Draw text on the watermark palette
$watermark->annotateImage($draw, 10, 12, 0, $text);

// Draw text on the mask palette
$draw->setFillColor('white');
$mask->annotateImage($draw, 11, 13, 0, $text);
$mask->annotateImage($draw, 10, 12, 0, $text);
$draw->setFillColor('black');
$mask->annotateImage($draw, 9, 11, 0, $text);

// This is apparently needed for the mask to work
$mask->setImageMatte(false);

// Apply mask to watermark
$watermark->compositeImage($mask, Imagick::COMPOSITE_COPYOPACITY, 0, 0);

// Overlay watermark on image
$image->compositeImage($watermark, Imagick::COMPOSITE_DISSOLVE, 0, 0);

// Set output image format
$image->setImageFormat('png');

// Output the new image
header('Content-type: image/png');
echo $image;

?>

Result:
+ = =>

In this example I create several images. The first image ($watermark) is grey-scale, and the second image ($mask) is pure black for the parts I want to be transparent and white for the parts I want to keep. When I apply the mask by combining the images, any grey shades found in $mask as a result of anti-aliasing will be semi-transparent and result in smoother edges.

In the command-line version of this code, the outside edges of the transparent image are clipped before overlaying the watermark. However, there appears to be a bug that prevents compositeImage() from preserving the position defined by setGravity(), so if I were to clip the edges then my watermark would lose its place at the bottom right and be re-positioned in the top-left corner. To get around this foolish behavior, the palettes are created with the same dimensions as the source image and no clipping takes place.

Tile text over the whole image
Code:
<?php

// Create objects
$image = new Imagick('mug.png');
$watermark = new Imagick();

// Watermark text
$text = 'Copyright';

// Create a new drawing palette
$draw = new ImagickDraw();
$watermark->newImage(140, 80, new ImagickPixel('none'));

// Set font properties
$draw->setFont('Bookman-Demi');
$draw->setFillColor('grey');
$draw->setFillOpacity(.5);

// Position text at the north-west of the watermark
$draw->setGravity(Imagick::GRAVITY_NORTHWEST);

// Draw text on the watermark
$watermark->annotateImage($draw, 10, 10, 0, $text);

// Position text at the south-east of the watermark
$draw->setGravity(Imagick::GRAVITY_SOUTHEAST);

// Draw text on the watermark
$watermark->annotateImage($draw, 5, 15, 0, $text);

// Repeatedly overlay watermark on image
for($w = 0; $w < $image->getImageWidth(); $w += 140) {
    for($h = 0; $h < $image->getImageHeight(); $h += 80) {
        $image->compositeImage($watermark, Imagick::COMPOSITE_OVER, $w, $h);
    }
}

// Set output image format
$image->setImageFormat('png');

// Output the new image
header('Content-type: image/png');
echo $image;

?>

Result:


This example uses transparency with setFillOpacity() rather than an image mask, and recursively tiles the watermark all over the image. Fun stuff.

October 3 2011, 7:28 pm
Web Dev : Comments (2)