<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-8229071700931727949</id><updated>2009-12-18T16:17:43.548-07:00</updated><title type='text'>Cetuscript Systems</title><subtitle type='html'>Your source for PHP 5, MySQL, and Mac OS X software development.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cetuscript.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default?orderby=updated'/><link rel='alternate' type='text/html' href='http://cetuscript.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>cetuscript</name><uri>http://www.blogger.com/profile/04442755161077569469</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8229071700931727949.post-1551786094156528750</id><published>2008-04-08T16:33:00.001-06:00</published><updated>2008-04-08T16:36:24.909-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='website'/><category scheme='http://www.blogger.com/atom/ns#' term='Cetuscript'/><title type='text'>Updated My Website a Bit</title><content type='html'>&lt;a href='http://www.cetuscript.com/' target='_blank'&gt;www.cetuscript.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Come and check it out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8229071700931727949-1551786094156528750?l=cetuscript.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cetuscript.blogspot.com/feeds/1551786094156528750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8229071700931727949&amp;postID=1551786094156528750' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/1551786094156528750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/1551786094156528750'/><link rel='alternate' type='text/html' href='http://cetuscript.blogspot.com/2008/04/updated-my-website-bit.html' title='Updated My Website a Bit'/><author><name>cetuscript</name><uri>http://www.blogger.com/profile/04442755161077569469</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='06106068532552351621'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8229071700931727949.post-3110910091998905717</id><published>2008-01-24T19:45:00.000-07:00</published><updated>2008-01-24T19:49:47.851-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jscript'/><category scheme='http://www.blogger.com/atom/ns#' term='source'/><category scheme='http://www.blogger.com/atom/ns#' term='asp'/><title type='text'>Simple Upload with Classic ASP/jscript</title><content type='html'>A project of mine, sitting on classic ASP, needed to upload a file. I've uploaded files with php and WebObjects - this, I thought, would be easy with ASP. Famous last words.&lt;br /&gt;&lt;br /&gt;I suppose it would be easy if I installed or paid for a 3rd party solution. But I didn't want to do that. And I felt a bit peeved that ASP was requiring me to have to install 3rd party software to do something as fundamental as uploading a file. What were the guys at Microsoft thinking?&lt;br /&gt;&lt;br /&gt;Anyhow, this leads us to the second problem. Finding good documentation about ASP, and good documentation about ASP using jscript is an extraordinarily frustrating task. So, for you, here is my solution. It's pretty basic. But it shows how it can be done.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cetuscript.com/downloads/upload.asp.zip"&gt;Upload Sample&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In this sample, the form just returns one value. Trying to handle more than one value is problematic because of the limits in jscript and how ASP communicates with it.&lt;br /&gt;&lt;br /&gt;Solution goes as follows...&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Take the binary object returned by Request.binaryRead stuff it into an ADODB.RecordSet field. The type of the field is text.&lt;/li&gt;&lt;li&gt;Pull out the text so we can find the start and end positions of the data of the uploaded file.&lt;/li&gt;&lt;li&gt;Slice the header information for the uploaded data.&lt;/li&gt;&lt;li&gt;Take the binary object and write it to a binary ADODB.Stream. Offset to the start and read off (end-start) bytes.&lt;/li&gt;&lt;/ul&gt;Now we have, in an array, the binary data for the file, number of bytes of the data, and the header info for the file. From here, we can write the data to a file or add it to a database.&lt;br /&gt;&lt;br /&gt;So. To just get the data, I have to bounce the data to a RecordSet then to a string object to find out where the data is. Then stuff it into a binary Stream to pull out the part I want. The "multipart/form-data" encoding is not complicated. But the ASP nonsense is.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size: 8px;"&gt;&amp;lt;%@ Language=JScript %&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt; &amp;lt;head&amp;gt;&lt;br /&gt;   &amp;lt;title&amp;gt;Test Upload&amp;lt;/title&amp;gt;&lt;br /&gt; &amp;lt;/head&amp;gt;&lt;br /&gt; &amp;lt;body&amp;gt;&lt;br /&gt;   &amp;lt;center&amp;gt;&lt;br /&gt;     &amp;lt;div align='left' style='width:400px;padding:10px;border:2px solid gray'&amp;gt;&lt;br /&gt;       &amp;lt;div&amp;gt;&lt;br /&gt;         &amp;lt;div&amp;gt;&lt;br /&gt;           &amp;lt;%&lt;br /&gt;             var  info = simpleUpload();&lt;br /&gt;            &lt;br /&gt;             if( null != info )&lt;br /&gt;               {&lt;br /&gt;                 type      = contentTypeFromHeader( info[2] );&lt;br /&gt;                 filename  = filenameFromHeader( info[2] );&lt;br /&gt;&lt;br /&gt;                 Response.write( "&amp;lt;div style='background:lightgray;border:1px dashed black;margin:0 0 10px;padding:3px'&amp;gt;" );&lt;br /&gt;                 Response.write( "&amp;lt;span style='font-weight:bold'&amp;gt;Upload Report&amp;lt;/span&amp;gt;" );&lt;br /&gt;                 Response.write( "&amp;lt;pre style='font-family:monospace'&amp;gt;" );&lt;br /&gt;                 Response.write( "length   = " + info[1] + "\n" );&lt;br /&gt;                 Response.write( "type     = " + type + "\n" );&lt;br /&gt;                 Response.write( "filename = " + filename );&lt;br /&gt;                 Response.write( "&amp;lt;/pre&amp;gt;" );&lt;br /&gt;                 Response.write( "&amp;lt;/div&amp;gt;" );&lt;br /&gt;                &lt;br /&gt;                 var  stream      = Server.CreateObject( "ADODB.Stream" );&lt;br /&gt;                 stream.open();&lt;br /&gt;                 stream.type      = 1;&lt;br /&gt;                 stream.position  = 0;&lt;br /&gt;                &lt;br /&gt;                 stream.write( info[0] );&lt;br /&gt;                 stream.saveToFile( Server.MapPath( "./dump/" + filename ), 2 );&lt;br /&gt;                 stream.close();&lt;br /&gt;&lt;br /&gt;                 if( null != filename )&lt;br /&gt;                   {&lt;br /&gt;                     Response.write( "&amp;lt;div&amp;gt;" );&lt;br /&gt;                     Response.write( "&amp;lt;img src='./dump/" + filename + "' /&amp;gt;" );&lt;br /&gt;                     Response.write( "&amp;lt;/div&amp;gt;" );&lt;br /&gt;                   }&lt;br /&gt;               }&lt;br /&gt;           %&amp;gt;&lt;br /&gt;         &amp;lt;/div&amp;gt;&lt;br /&gt;       &amp;lt;/div&amp;gt;&lt;br /&gt;    &lt;br /&gt;       &amp;lt;div style='clear:both;margin-top:10px'&amp;gt;&lt;br /&gt;         &amp;lt;form style='padding:0;margin:0' method='POST' enctype='multipart/form-data'&amp;gt;&lt;br /&gt;           &amp;lt;div&amp;gt;&lt;br /&gt;             &amp;lt;input type='file' name='source' /&amp;gt;&lt;br /&gt;           &amp;lt;/div&amp;gt;&lt;br /&gt;           &amp;lt;div style='margin-top:10px'&amp;gt;&lt;br /&gt;             &amp;lt;input type='submit' value='Upload' /&amp;gt;&lt;br /&gt;           &amp;lt;/div&amp;gt;&lt;br /&gt;         &amp;lt;/form&amp;gt;&lt;br /&gt;       &amp;lt;/div&amp;gt;&lt;br /&gt;     &amp;lt;/div&amp;gt;&lt;br /&gt;   &amp;lt;/center&amp;gt;&lt;br /&gt; &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&amp;lt;%&lt;br /&gt;function simpleUpload()&lt;br /&gt;{&lt;br /&gt; if( 0 == Request.totalBytes )&lt;br /&gt;   return null;&lt;br /&gt;&lt;br /&gt; var  blob       = Request.binaryRead( Request.totalBytes );&lt;br /&gt; var  recordSet  = Server.CreateObject( "ADODB.RecordSet" );&lt;br /&gt;&lt;br /&gt; //' 201 = adLongVarChar&lt;br /&gt; recordSet.fields.append( "raw", 201, Request.totalBytes );&lt;br /&gt; recordSet.open();&lt;br /&gt; recordSet.addNew();&lt;br /&gt; recordSet.fields(0).appendChunk( blob );&lt;br /&gt;&lt;br /&gt; var  str  = "" + recordSet.fields(0);&lt;br /&gt; var  eol      = "\r\n";&lt;br /&gt; var  blank    = "\r\n\r\n";&lt;br /&gt; var  marker  = str.substr( 0, str.indexOf( eol ) + eol.length );&lt;br /&gt;&lt;br /&gt; var  start    = str.indexOf( blank, marker.length );&lt;br /&gt; start += blank.length;&lt;br /&gt; //' the last marker has a "--" at the end of it&lt;br /&gt; var  end      = str.length - (marker.length + 2); &lt;br /&gt; var  length  = end - start;&lt;br /&gt;&lt;br /&gt; var  header  = str.slice( marker.length, start - blank.length ).split( eol );&lt;br /&gt;&lt;br /&gt; var  data  = Server.CreateObject("ADODB.Stream");&lt;br /&gt; data.open();&lt;br /&gt; data.type      = 1;&lt;br /&gt; data.position  = 0;&lt;br /&gt; data.write( blob );&lt;br /&gt; data.position = start;&lt;br /&gt;&lt;br /&gt; return new Array( data.read( length ), end-start, header );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function findValueForKeyFromHeader( header, key )&lt;br /&gt;{&lt;br /&gt; key = key.toLowerCase();&lt;br /&gt; var  i;&lt;br /&gt; for( i=0; i&amp;lt;header.length; ++i )&lt;br /&gt;   {&lt;br /&gt;     line = header[i].split( ": " );  //' again, weak.&lt;br /&gt;     if( key == line[0].toLowerCase() )&lt;br /&gt;       return line[1];&lt;br /&gt;   }&lt;br /&gt; return null;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function contentTypeFromHeader( header )&lt;br /&gt;{&lt;br /&gt; return findValueForKeyFromHeader( header, "Content-Type" );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function filenameFromHeader( header )&lt;br /&gt;{&lt;br /&gt; var  params = findValueForKeyFromHeader( header, "Content-Disposition" );&lt;br /&gt; if( null == params )&lt;br /&gt;   return null;&lt;br /&gt;&lt;br /&gt; var  kvs = params.split( "; " );  //' I know this is weak&lt;br /&gt; var  i;&lt;br /&gt; for( i=0; i&amp;lt;kvs.length; ++i )&lt;br /&gt;   {&lt;br /&gt;     kv = kvs[i].split( "=" );&lt;br /&gt;     if( "filename" == kv[0].toLowerCase() )&lt;br /&gt;       {&lt;br /&gt;         var  filename  = kv[1].substr( 1, kv[1].length-2 );  //' remove the quotes&lt;br /&gt;         var  slash      = filename.lastIndexOf( "\\" );  //' only IE eh.&lt;br /&gt;         if( -1 != slash )&lt;br /&gt;           filename = filename.substring( slash + 1, filename.length );&lt;br /&gt;        &lt;br /&gt;         return filename;&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt; return null;&lt;br /&gt;}&lt;br /&gt;%&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;digg_url = 'http://cetuscript.blogspot.com/2007/01/simple-upload-with-classic-aspjscript.html';digg_skin = 'compact';&lt;/script&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8229071700931727949-3110910091998905717?l=cetuscript.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cetuscript.blogspot.com/feeds/3110910091998905717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8229071700931727949&amp;postID=3110910091998905717' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/3110910091998905717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/3110910091998905717'/><link rel='alternate' type='text/html' href='http://cetuscript.blogspot.com/2007/01/simple-upload-with-classic-aspjscript.html' title='Simple Upload with Classic ASP/jscript'/><author><name>cetuscript</name><uri>http://www.blogger.com/profile/04442755161077569469</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='06106068532552351621'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8229071700931727949.post-7525644898246111330</id><published>2008-01-24T19:00:00.000-07:00</published><updated>2008-01-24T19:49:11.046-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='innerHTML'/><category scheme='http://www.blogger.com/atom/ns#' term='responseText'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='source'/><title type='text'>Javascript - queryForInnerHTML</title><content type='html'>I wrote a little set of functions to help me do asynchronous http queries. This set is really lightweight but handy when you want to fill out a part of your page with something that might take a long time or if you want to update something without the user having to reload the page. &lt;br /&gt;&lt;br /&gt;&lt;i&gt;queryForInnerHTML( query, elementId [, postQueryFunc, postArgs] );&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;query&lt;/b&gt; is an http query like "http://host.com/query/lookup.php?stuff=this"&lt;br /&gt;&lt;br /&gt;&lt;b&gt;elementId&lt;/b&gt;  is the id of the element whose innerHTML will be replaced with the response from the query.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;postQueryFunc&lt;/b&gt;  and &lt;b&gt;postArgs&lt;/b&gt;  are used after the innerHTML is replaced. This provides you with a sort of callback. &lt;br /&gt;&lt;br /&gt;&lt;pre style='font-size:smaller'&gt;var  global_AJAX_Array  = new Array();&lt;br /&gt;var  global_AJAX_Count  = 0;&lt;br /&gt;&lt;br /&gt;function makeNewAjax()&lt;br /&gt;  {&lt;br /&gt;    if( window.XMLHttpRequest ) &lt;br /&gt;      {&lt;br /&gt;        return new XMLHttpRequest(); &lt;br /&gt;      } &lt;br /&gt;    else &lt;br /&gt;      {&lt;br /&gt;        return  new ActiveXObject("MSXML2.XMLHTTP");&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;function findAjaxIndex()&lt;br /&gt;  {&lt;br /&gt;    var  index;&lt;br /&gt;    for( index = 0; index &lt; global_AJAX_Count; ++index )&lt;br /&gt;      if( null == global_AJAX_Array[index] )&lt;br /&gt;        return index;&lt;br /&gt;    ++global_AJAX_Count;&lt;br /&gt;    return index;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;function queryForInnerHTML( query, elementId, postQueryFunc, postArgs )&lt;br /&gt;  {&lt;br /&gt;    var  body;&lt;br /&gt;    var  index = findAjaxIndex();&lt;br /&gt;    global_AJAX_Array[index] = makeNewAjax();&lt;br /&gt;        &lt;br /&gt;    body   = "var ajax = global_AJAX_Array[" + index + "];\n";&lt;br /&gt;    body  += "if( 4 == ajax.readyState )\n";&lt;br /&gt;    body  += "{ document.getElementById(\"" + elementId + "\").innerHTML = ajax.responseText;\n";&lt;br /&gt;    if( null != postQueryFunc )&lt;br /&gt;      {&lt;br /&gt;        body += postQueryFunc;&lt;br /&gt;        &lt;br /&gt;        if( null == postArgs )&lt;br /&gt;          body += "();\n";&lt;br /&gt;        else&lt;br /&gt;          body += "(" + postArgs + ");\n"&lt;br /&gt;      }&lt;br /&gt;    body  += "global_AJAX_Array[" + index + "] = null;\n";&lt;br /&gt;    body  += " }\n";&lt;br /&gt;    &lt;br /&gt;    global_AJAX_Array[index].onreadystatechange = new Function( body );&lt;br /&gt;    &lt;br /&gt;    global_AJAX_Array[index].open( "GET", query, true );&lt;br /&gt;    global_AJAX_Array[index].send(null);&lt;br /&gt;  }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There's more stuff that could be done here like formatting the response with xml/xsl. But for what I've needed for something quick, this has worked well.&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;digg_url = 'http://cetuscript.blogspot.com/2008/01/javascript-queryforinnerhtml.html';digg_skin = 'compact';&lt;/script&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8229071700931727949-7525644898246111330?l=cetuscript.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cetuscript.blogspot.com/feeds/7525644898246111330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8229071700931727949&amp;postID=7525644898246111330' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/7525644898246111330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/7525644898246111330'/><link rel='alternate' type='text/html' href='http://cetuscript.blogspot.com/2008/01/javascript-queryforinnerhtml.html' title='Javascript - queryForInnerHTML'/><author><name>cetuscript</name><uri>http://www.blogger.com/profile/04442755161077569469</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='06106068532552351621'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8229071700931727949.post-8336604371231215440</id><published>2008-01-18T11:19:00.000-07:00</published><updated>2008-01-18T11:24:13.916-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mutantjedi'/><title type='text'>I'm going to be moving stuff here</title><content type='html'>I've been writing a lot of my software development posts to another blog. I'm going to be moving them here and keep the focus here for that sort of thing and the focus of the other blog more general ramblings.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8229071700931727949-8336604371231215440?l=cetuscript.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://mutantjedi.blogspot.com' title='I&apos;m going to be moving stuff here'/><link rel='replies' type='application/atom+xml' href='http://cetuscript.blogspot.com/feeds/8336604371231215440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8229071700931727949&amp;postID=8336604371231215440' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/8336604371231215440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/8336604371231215440'/><link rel='alternate' type='text/html' href='http://cetuscript.blogspot.com/2008/01/im-going-to-be-moving-stuff-here.html' title='I&apos;m going to be moving stuff here'/><author><name>cetuscript</name><uri>http://www.blogger.com/profile/04442755161077569469</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='06106068532552351621'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8229071700931727949.post-2680688722555191000</id><published>2007-04-13T20:22:00.000-06:00</published><updated>2007-04-13T20:25:35.301-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Photoshop'/><category scheme='http://www.blogger.com/atom/ns#' term='Donationware'/><category scheme='http://www.blogger.com/atom/ns#' term='QuickTime'/><category scheme='http://www.blogger.com/atom/ns#' term='MovieMerge'/><title type='text'>MovieMerge</title><content type='html'>&lt;a href='http://www.cetuscript.com/projects/MovieMerge' target='_blank'&gt;&lt;img src='http://www.cetuscript.com/images/MovieMerge.jpg' style='float:right' /&gt;&lt;/a&gt;MovieMerge is a simple little application that you can use to blend images over top of movies. You can use it to quickly add text or watermarks to your movies. &lt;br /&gt;&lt;br /&gt;Using Photoshop, you could create interesting borders for your movie. A good place to learn how to create &lt;a href='http://www.photoshopbasics.com/pages/magic_photoshop.htm' target='_blank'&gt;Photoshop magic&lt;/a&gt; is &lt;a href='http://www.photoshopbasics.com' target='_blank'&gt;www.photoshopbasics.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The impetus for the application was that a friend of mine took some videos of his dog playing in the snow. However he took the videos in a portrait orientation. He wanted rotate the video plus make it 4x3 (rather than 3x4). The tools that I have kicking on my Mac could do the rotation easy enough. But when I tried to make it 4x3, invariably the movie got stretched. &lt;br /&gt;&lt;br /&gt;With Cocoa, Core Data, and QuickTime, writing a custom application is very easy and very quick. Well.... okay. QuickTime and threads can be a real pain. Really great technology, QuickTime, but it shows its age when it comes to threads. &lt;br /&gt;&lt;br /&gt;The software is released as Donationware. If you like it, donate some money to me, if you wish. &lt;br /&gt;&lt;br /&gt;&lt;div class="mj_tag"&gt;Tags: &lt;a href="http://technorati.com/tag/MovieMerge" rel="tag"&gt;MovieMerge&lt;/a&gt;  &lt;a href="http://technorati.com/tag/QuickTime" rel="tag"&gt;QuickTime&lt;/a&gt;  &lt;a href="http://technorati.com/tag/Donationware" rel="tag"&gt;Donationware&lt;/a&gt;  &lt;a href="http://technorati.com/tag/Photoshop" rel="tag"&gt;Photoshop&lt;/a&gt;  &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8229071700931727949-2680688722555191000?l=cetuscript.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.cetuscript.com/projects/MovieMerge' title='MovieMerge'/><link rel='replies' type='application/atom+xml' href='http://cetuscript.blogspot.com/feeds/2680688722555191000/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=8229071700931727949&amp;postID=2680688722555191000' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/2680688722555191000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8229071700931727949/posts/default/2680688722555191000'/><link rel='alternate' type='text/html' href='http://cetuscript.blogspot.com/2007/04/moviemerge.html' title='MovieMerge'/><author><name>cetuscript</name><uri>http://www.blogger.com/profile/04442755161077569469</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='06106068532552351621'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>