Fun With Structures (Help Me Name This Post)

I apologize for the extremely lame title of this post. It's worth reading, trust me. 250 bonus points to the commenter who comes up with the best alternate title.

Last night I was tightening up another release of my PPTUtils component when I hit a roadblock with one of the demos in the package.

The component returns an array containing an element that represents each slide in a PowerPoint presentation. One of the items in each element is the binary contents of the background image on the given slide. Due to the nature of PowerPoint, many of these images could be duplicates. When processing the array of slides I wanted a way to avoid writing these duplicate images to disk.

My first thought was to insert the binary data data into a struct and to then do a structFindValue() to see if that data already existed in the struct before inserting it. Since I was using the struct key name as the image name, if the data existed in the struct then I'd simply assign key name returned from structFindValue() as the image name (thus preventing a duplicate write to disk). The problem with this approach was that the image data was in binary form and structFindValue() can only search for simple strings in a struct. The fix was to convert the binary data to base64 and insert the base64 string into the struct. Since the duplicates would have an identical base64 representation this would allow me to find the image in the struct and avoid writing to disk again.

Seems a bit complex, but here's some code to make it a little easier to understand.

First I'll create a simple image:

<!--- create a new 100x100 image with a red background --->
<cfset one = imageNew("", 100, 100, "rgb", "red") />
<cfset oneAsBase64 = toBase64(one) />
<cfimage action="writeToBrowser" source="#one#" />

Which gives me:

Next create another image - but slightly different:

Now insert the base64 representations of those images in a struct and dump it:

<cfset testStruct = {imgOne=oneAsBase64, imgTwo=twoAsBase64} />
<cfdump var="#testStruct#">

Now find the second image in that struct (imagine this step within a loop so as to avoid re-insertion).

<cfdump var="#structFindValue(testStruct,twoAsBase64)#">

Which gives me:

Here's the code in whole:

<!--- create a new 100x100 image with a red background --->
<cfset one = imageNew("", 100, 100, "rgb", "red") />
<cfset oneAsBase64 = toBase64(one) />
<cfimage action="writeToBrowser" source="#one#" />
<br />
<!--- create a new 100x100 image with a blue background --->
<cfset two = imageNew("", 100, 100, "rgb", "blue") />
<cfset twoAsBase64 = toBase64(two) />
<cfimage action="writeToBrowser" source="#two#" />

<cfset testStruct = {imgOne=oneAsBase64, imgTwo=twoAsBase64} />
<cfdump var="#testStruct#">
<br/>
<cfdump var="#structFindValue(testStruct,twoAsBase64)#">

So would there have been another way to do this? Sure! How about using the arrayFind() UDF from CFLib? This UDF uses the underlying Java indexOf() method on the array to check to see if the value exists.

Here's the altered code:

<!---
The arrayFind function uses the java.util.list indexOf function to find an element in an array.
v1 by Nathan Dintenfas.

@param array     Array to search. (Required)
@param valueToFind     Value to find. (Required)
@return Returns a number, 0 if no match is found.
@author Larry C. Lyons (larryclyons@gmail.com)
@version 2, August 10, 2007
--->

<cffunction name="arrayFind" access="public" hint="returns the index number of an item if it is in the array" output="false" returntype="numeric">
   <cfargument name="array" required="true" type="array">
   <cfargument name="valueToFind" required="true" type="string">
   <cfreturn (arguments.array.indexOf(arguments.valueToFind)) + 1>
</cffunction>

<!--- create a new 100x100 image with a red background --->
<cfset one = imageNew("", 100, 100, "rgb", "red") />
<cfset oneAsBase64 = toBase64(one) />
<cfimage action="writeToBrowser" source="#one#" />
<br />
<!--- create a new 100x100 image with a blue background --->
<cfset two = imageNew("", 100, 100, "rgb", "blue") />
<cfset twoAsBase64 = toBase64(two) />
<cfimage action="writeToBrowser" source="#two#" />

<cfset testArr = [oneAsBase64,twoAsBase64] />
<cfdump var="#testArr#">

<cfdump var="#arrayFind(testArr,twoAsBase64)#">
<!--- outputs '2' --->

Comments
Inspired by a comment in my last post I have decided today is pants optional day. As such your post title should be called: "Fun with Structures - the pants optional way".
# Posted By Joshua Cyr | 1/30/08 1:47 PM
Dang it, then I better get some different images for my demo.... :D
# Posted By todd sharp | 1/30/08 2:28 PM
When Structures Collide

There's Always a Better Way With Java

oneAsBase64, twoAsBase64, threeAsBase64, you get the picture

Sometimes, All You Really Need is an Array

heh.
# Posted By Jason | 1/31/08 12:08 PM
"Stuck on Structures"
# Posted By Joshua Hublar | 2/26/08 8:11 AM

Calendar

Sun Mon Tue Wed Thu Fri Sat
     12
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31       

Subscribe

Enter your email address to subscribe to this blog.

Tags

actionscript ajax blogging cfsnippets coldfusion flash forms flex funny stuff misc model-glue off topic personal project learn slidesix sql

Recent Comments

Adding Auto Generated Code Downloads to BlogCFC
ada5fsa said: http://www.mountwashingto... http://extjs.com/forum/me... h... [More]

BlogCFC Survey #2
ada5fsa said: http://www.mountwashingto... http://extjs.com/forum/me... h... [More]

Most Difficult Captcha Of All Time
kokkooo said: [url=http://synchrophase.info/...]消費者金融 ブラック[/url] [url=http://geji-geji.com/]消費者金融ブラック[/url] [url=http... [More]

Most Difficult Captcha Of All Time
kokkooo said: <a href="http://synchrophase.info/...">消費者金融 ブラック</a> <a href="http://gej... [More]

Using A PlayStation 2 HDD In Your PC
Vodin said: Well dang. Thanks man, my uncle who owns a Video Game shop had a PS2 harddrive in the junk box, I sn... [More]

RSS


coldfusionbloggers

FullAsAGoog MXNA

Consumed By Feed-Squirrel.com