fogbound.net




Fri, 11 Nov 2011

Imaginary Tech Conversation

— SjG @ 3:14 pm

Coder #1: Man, revision control sucks.
Coder #2: What? Are you insane?
Coder #1: Insane? I don’t think so.
Coder #2: How can you say revision control sucks, then?
Coder #1: Well, I’m stuck using SVN.
Coder #2: Subversion isn’t so bad. Especially with the new merge tracking stuff from version 1.5. It’s pretty easy to use.
Coder #1: Yeah, well, I stand by my assertion. It sucks.
Coder #2: Can you be more specific?
Coder #1: Have you tried using SVN in a mixed environment? Say Windows, Linux, and Mac OS?
Coder #2: It’s not going to be line-ending issues. Oh, I see. You’re talking about case-sensitive versus case-insensitive filesystems.
Coder #1: I wish it was that easy. That’s crappy, but you can work around it.
Coder #2: Then?
Coder #1: A riddle for you. When is UTF-8 not UTF-8?
Coder #2: Huh?
Coder #1: When it’s in a filename.
Coder #2: [clicks, reads]
Coder #1: But I guess if you don’t have any Macs or ZFS around, you’re fine.
Coder #2: Holy Linus on a unicycle! Well, I guess it’s back to dated tar files…
Coder #3: Use GIT, you IDIOT!


Fri, 21 Oct 2011

Using PHPExcel with Yii

— SjG @ 2:18 pm

I was running into problems with conflicting autoloaders when I tried to use PHPExcel with the Yii framework. There are instructions out on the web on how to resolve this, but they are only useful if you’re not creating instances of Yii active record models while you’re using PHPExcel. That’s fine if you’re using Yii to create an Excel spreadsheet from already instantiated Yii classes, but my need is to read an Excel spreadsheet and import its data into my database.

It turns out that this is fairly straightforward as well. The trick is in realizing that PHPExcel is registering its autoloader when it’s instantiated, so you don’t need to register it yourself.

public function actionImport()
  {
  $message = '';
  if (!empty($_POST))
     {
    $file = CUploadedFile::getInstanceByName('import');
    $spec = Yii::app()->basePath.'/data/imports/'.$file->name;
    $file->saveAs($spec);
    spl_autoload_unregister(array('YiiBase','autoload'));
    require(Yii::app()->basePath.'/extensions/phpexcel/Classes/PHPExcel.php');
    spl_autoload_register(array('YiiBase', 'autoload'));
    try {
         $inputFileType = PHPExcel_IOFactory::identify($spec); 
         $objReader = PHPExcel_IOFactory::createReader($inputFileType);  
         if ($inputFileType != 'CSV')
            {
            $objReader->setReadDataOnly(true);
            }
        $objPHPExcel = $objReader->load($spec); 
        $objWorksheet = $objPHPExcel->setActiveSheetIndex(0);
        $highestRow = $objWorksheet->getHighestRow();
        for ($row = 1;$row < $highestRow+1; $row++)
             {
             $myObjThing = new MyObject; // Yii AR model
             $myObjThing->someField = $objWorksheet->getCellByColumnAndRow(1, $row)->getValue();
             $myObjThing->otherField = $objWorksheet->getCellByColumnAndRow(5, $row)->getValue();
             $myObjThing->save(false);
             $myObjThing->detachBehaviors(); // PHP < 5.3 memory management
             unset($myObjThing);
             }
        }
    catch (Exception $e)
       {
       $message = 'There was a problem handling your file. Technical details: '.$e->getMessage();
       }
    if (! empty($message))
       {
       Yii::app()->user->setFlash('error',$message);
       }
    }		
  $this->render('import');
  }

Pretend WordPress didn’t hose the formatting on that …


Tue, 18 Oct 2011

Publishing Old Projects

— SjG @ 9:52 pm

I’ve been publishing a bunch of old projects that I may have posted here, or simply left on my hard drive to suffer the slings and arrows of outrageous bit-rot. Most of these are projects that I created for some specific purpose or another, and have either coded to the point where I’m satisfied with them, or abandoned them.

I’m publishing this stuff in the hopes that it’ll be useful to somebody somewhere. In some cases, the code’s primary use may be as an example of how not to accomplish a task. In other cases, they’re projects that are being used in mission-critical operations, and so are reasonably robust.

I’ll be maintaining them on GitHub, if you want to get creative with the definition of “maintaining.”


Sun, 25 Sep 2011

Photoshop scripting with Javascript

— SjG @ 6:41 pm

I’ve played with the Javascript interface to Photoshop for a couple of years. Conceptually, it’s great — a simple, powerful, interpreted language like Javascript, with an API to interface to one of the best image-processing packages available. In practice, it’s not as good as it is in concept, but it’s still pretty good. The API doesn’t include all of Photoshop’s functionality directly, and there are a lot of things you need to execute as fairly obscure event actions. These event actions aren’t documented, but can be determined by activating a plug-in which logs everything that you do using the Photoshop GUI — you can then read through these logs, and copy the actions you need.

Still, there are some real advantages to using this Javascript interface, as opposed to something designed for the purpose like, say, Processing. You can use the Photoshop UI for controlling inputs to your script (set foreground colors, select portions of the image, select specific layers, etc.), and output your manipulations directly into Photoshop layers.

I’ll be posting here shortly a library I’ve created for easily building dialog panels for setting script options. I find that most manipulations I want to do have a set of variables, and I’d rather not tweak the code each time I want to change them.

This library was originally written under Photoshop 10 (aka CS3). Under version 11 (aka CS4), it was less stable. Sometimes it would crash out at odd places complaining that I was referencing properties of undefined objects. Because there have been memory leaks and other issues with the Javascript interpreter, these seemingly random failures were annoying but not too surprising. When it came to version 12 (aka CS5), I was rarely able to run my scripts at all. What made it frustrating was the apparent randomness of the crashes. I could print a variable to the console, and the very next line would crash out with an “undefined object” error when referencing that variable.
To make a long story short, I was able to track down the issue. It turns out that in iterations, declaring variables matters. That is to say:
for (i in someCollection)
{
$.writeln(i['someAttribute']);
}

will cause random crashes, but
for (var i in someCollection)
{
$.writeln(i['someAttribute']);
}

runs beautifully. Now, I “knew” that the var keyword is optional and used for specifying scope, but I never had any idea that there could be an issue within the scope of a simple loop. Obviously, Javascript didn’t know that I intended i to be a variable on each iteration — perhaps it thinks I meant for i to be a 1957 Chevy Belair on some iterations.

In any case, having cracked the code as it were, I have proceeded to enhance and add to my library. After a little more testing, I’ll be posting it here or on GitHub.


Sat, 24 Sep 2011

Ffun ffmpeg ffunctionality

— SjG @ 2:59 pm

I’ve been processing a collection of product videos which came to me in a huge variety of sizes, aspect ratios, and qualities. I need to re-encode them to work in HTML 5, but, more importantly, I need to make them fit into a common player space on the web page.

It turns out that newer versions of ffmpeg support not only cropping, but also padding, and you can even do both operations at once!

For example, I had a source video that was originally 16:9, but had been letterboxed to 4:3, and then had two different sets of labels added. I needed to crop out the letterboxed portion and the top set of labels, and make the result fit nicely into 16:9. So I used VLC, a screen capture utility, and Photoshop to get the measurements. Then I used ffmpeg to crop the relevant section and pad it out to fit into my space (in this case, I’m left aligning the video in the padded output):


ffmpeg -i original/converted.wmv -vf crop=394:295:6:0,pad=524:295:0:0:0xFFFF00 -sameq converted.mov

That’s cropping a 394 x 295 piece out of the original video (with the origin at 6 pixels from the left, and 0 pixels from the top), and then padding it out to 524 x 295 filling the padded area with bright yellow. The 524 x 295 is really close to 16:9 — and in a later process, it gets resized to the more standard 480 x 2721.

You can string together the padding and cropping in either order, depending on the effect you’re trying to achieve.

1I’m sure some educated person out there could tell me why video standards are so confused/confusing, down to the non-square pixels. While a true 16:9 would dictate 480 x 270 pixels, everybody seems to use 480 x 272. Why? The only thing I can figure out is that 272 is evenly divisible by a power of 2, which probably made display hardware cheaper to manufacture. As you can see, my resizing adds a bit of distortion, but at these resolutions, it doesn’t really matter.