How to Drastically Reduce an Overgrown iPhoto Library by Starting from Scratch

Posted July 20, 2011 by Greg Martin
Categories: Uncategorized

Note: Below are the steps I took to cleanup my personal iPhoto library.  Your mileage may vary, and as always, before doing something drastic like this, make sure you have a good backup.  Also, this was done using iPhoto ’11.  I don’t know if the same process works on previous versions.  Also, this tutorial only outlines how to save your photos and events.  I did not bother saving any albums or projects from my previous library.  I highly recommend reading through the steps prior to going to the process to ensure you are comfortable with everything that is required.

I’m looking forward to Apple’s OS X Lion upgrade that was released today.  I’m hoping to breathe some life back into my MacBook Pro by doing a clean install and then just importing and installing only the things I need as I need them.  In investigating what was using up the majority of my hard drive space I discovered that my iPhoto library was using up 24 GBs of space.

24 GB!  That was shocking to me as I don’t take that many pictures.  What I’ve determined is that over the years of iPhoto upgrades my library has collected a lot of cruft.  Thumbnails, iPod Sync Versions, Originals and who knows what else seem to be using up a ton of space.

It is possible to get into the guts of an iPhoto library and try to manually remove junk like the above, however, you are almost guaranteed to screw something up and I would recommend to just avoid this idea altogether.

My solution instead, was to export all my photos, wipe out my existing library and create a new one from scratch.  I was able to reduce my library down to about 11 GB.  That’s a 13 GB savings in space with the loss of any photos!  Below are the steps to do this.

1. Re-Title All the Photos in Your Library

The first frustrating thing about iPhoto’s export functionality is that it does not have an option to export your Events in bulk to corresponding folders.  If it did, this tutorial would be 2 steps.  Instead, I had to export all my photos into one folder and then use a script to file them into folders correctly based on their filename.

To get the filenames consistent, first select all of your events, and from the “Photos” menu choose “Batch Change…”.  Then tell it to “Set Title to Event Name”.

This will update the titles for all your photos to look something like “My Event – 0001″.

2. Export All Photos to a Folder

Create a folder somewhere in your system to export everything to.  I created a folder called “Photos_Current” in my Downloads folder.  Now, again, select all your events and from the “File” menu, choose “Export…”.

From the “File Export” tab we have a decision to make.  When you modify a photo in iPhoto it keeps the original version as well as the updated version.  This is nice if you ever want to roll back an image, but not nice if you are looking to clean up some space.  For me, I assume that if I modified a photo, say I cropped it down, straightened it or removed red-eye, the current one is the one I really care about.  If you prefer the original version then that’s fine to, it means you can skip step 2b below.

So next I set the “Kind” to “Current” and the “File Name” to “Use title”.

This export might take a bit of time depending on the size of your library.

2b. 

This step is optional, if you chose to export Original instead of Current in the previous step, or you do not have any videos in your library, you can move on to step 3.

When exporting Current iPhoto does not properly export videos.  They show up as single frame files rather than full videos.  To correct this, we have to do another export similar to the above, but choosing “Original” and exporting that into a different folder.

Once that export is complete, you will need to manually copy the video files (could be of many types, MOV, MPG, AVI, MP4, etc…) into the first export.  Once those are copied over, you can delete the rest of the second export.

3. Trash Your Old Library

Again, make sure you have a backup, but if you do, go ahead and close iPhoto and delete your library.  Usually this is called “iPhoto Library” in your “Pictures” folder.

4. Organize Your Photos Into Foldres

So at this point we have one folder with all our files export named after the Events they were a part of.  This is where things require a bit of technical know-how.  Luckily for us, someone out there has already written a script to do just that.

You can follow the instructions at http://hints.macworld.com/article.php?story=20081108132735425 to learn how to run this script.

Once it is complete, you should now have a series of folders named the same as your original Events.

5. Create a New iPhoto Library

Open iPhoto.  Its going to complain about a missing library (remember we deleted it).  Just choose “Create New” and you can create a new “iPhoto Library” wherever you want, though I suggest just putting it back in the “Pictures Folder”

6. Import Your Photos Back In

This step is easy, just select all the folders that were created by the script, and drag them into iPhoto.  It will automatically being the import process and when it is done, you will see that it has turned all the folders back into Events.

And that’s it.  Not too bad and you get a huge space savings, or at least I did.

- Greg Martin

How I Stay Organized

Posted July 17, 2009 by Greg Martin
Categories: gtd, opinion, random

>I’ve always been a very organized person.  Though my habits for staying organized change rather frequently.  In grade school I recall cycling through a single divided notebook to a pee-chee for every class to a notebook for every class and back again.  College was no different.  One year, small 5×7 notebooks, color coded for each class to easily be able to grab them out of my bag (yeah, I know, huge dork, it doesn’t get any better…) to a meticulously organized binder with schedules I’d print out daily to manage my class and work schedules to spending way more money than I had on a Handspring Visor PDA (yeah, I was that guy and it was awesome).

In my post-college work life I’m no different.  What has changed is the amount of technology I can take advantage of.  Not too long ago I jumped on the Moleskine bandwagon, I think it lasted for a month, but I’m just not a paper (or writing) person.  For one, my handwriting is horrible not to mention slow.  The time it takes for me to write something that I will later not be able to read is not worth it.  Going to school in the 90′s and being subjected to keyboarding classes not once, not twice, but three times made me an excellent typist with 5th grade level handwriting.
So here are the current methods I follow and tools I use to stay organized.
Inbox as a To Do List
One thing that has been true since I first got email is that I’ve always use my inbox as a to do list.  If something is in my inbox then it requires some action, otherwise it gets deleted or archived.  It’s not anymore complicated than that.
Multiple Calendars
Separating items between different color coded calendars works well for me.  At the core I have a personal calendar, my work calendar and a calendar that has reoccurring events for when my various bills are due.  Beyond that I’m a big fan of subscribing to calendar feeds such as my TripIt calendar (more on that in a moment), birthdays and US holidays.
Things
I’ve tried a lot of different to do list applications.  Lately I’ve settled on Things.  The combination desktop application and iPhone application are worth the initial cost.  They key is to to get in the habit of using it.  I try to get every item down throughout the day and there is nothing more rewarding than checking things off.
Evernote
Evernote is a tool that I really like, and yet still find that I am not using it nearly as much as I should be.  My note taking habits are actually not very good.  I’m super OCD about tracking to do items, but general notes from meetings tend to be pretty light.  I’m currently trying to remedy this and Evernote is the tool that seems to fit my needs the best.
TripIt
Last, but not least, I have been traveling quite a bit in the last couple of years.  TripIt has become and invaluable tool for keeping track of my upcoming trips and the details for those trips (i.e. flight times, hotel reservations).  Being able to subscribe to my trip items in iCal and being able to see them mixed in with other items on my calendars saves me a lot of scheduling hassle.
I think the key components to each of these tools or methods is that they are all completely in sync with my iPhone.  A system that I can maintain while I’m away from my computer is critical for me.

Our First AppStore App

Posted June 29, 2009 by Greg Martin
Categories: Uncategorized

>Last week our client SonoSite launched their new iPhone application into the AppStore.  SonoSite makes portable ultrasound machines.  The application we built for them provides instructional video content for general ultrasound procedures as well as a host of other supporting information.  Check out the app at http://www.sonosite.com/products/sonoaccess/.

WWDC 2009

Posted June 1, 2009 by Greg Martin
Categories: apple, iphone, wwdc

>I will be attending Apple’s World Wide Developer Conference again this year.  Last year Steve Jobs announced the iPhone 3G at the keynote, I’m looking forward to seeing what they have in store for us this time.  WWDC is a pretty good event for developers.  I look forward to digging into some of the iPhone SDK 3.0 features that I have not yet had a chance to dig into.  The developer NDA doesn’t allow me to talk about 3.0 here, so for now I’ll just say that it looks like its going to be a pretty significant update.

Social Media Overload

Posted April 28, 2009 by Greg Martin
Categories: facebook, myspace, social media, twitter

>I’m starting to become overwhelmed with all the social media sites. I resisted Twitter for a long time, but I caved yesterday. For the most part I’ve been pretty good about keeping it simple. I killed my MySpace account years ago and have pretty much only used Facebook for keeping connected with folks I don’t see on a daily basis.

There is a big push now to find a use for these tools in the enterprise. Can Twitter really be a viable business tool? There are certainly some cases of it working, Zappos and Alaska Airlines to name a couple. Though I feel those users were not born out of trying to jump on the bandwagon, but rather seeing an opportunity to communicate better with customers.
I guess to me, it boils down to each individual case. Customers are smart, if you aren’t trying to communicate with them in a genuine manor they will know and respond in kind.

Using the Cloud

Posted March 31, 2009 by Greg Martin
Categories: amazon, apple, aws, iphone, random

>Over the years I’ve started countless projects by myself or with friends that have never been fully realized.  I’m still waiting for that one great idea that really drives me to create something from nothing.  In the mean time I am pretty happy bringing other people’s ideas to light, most of the time.

Without giving away too much detail, one of my current client projects is a pretty cool combination of technologies.  We are building an iPhone application with Amazon Web Services back-end.  As we’ve been building this it has occurred to me how many of my ideas in the past died because we would get bogged down in the details about where and how we were going to host it rather than just building it.

It’s thrilling to see all these cloud computing services springing up that really level the playing field for anyone with an idea to deploy, and more importantly scale if they find success.

I still don’t have that one great idea, but I feel like the roadblocks that existed in years past have lessened.

Once-A-Month Blog Challenge

Posted February 6, 2009 by Greg Martin
Categories: Uncategorized

>You might recall the Once-A-Week Blog Challenge that Joel and I started last year. Well, the wheels kinda fell off that wagon, but never fear, we have a new challenge, but this time we are lowering our expectations. We are both committing to getting at least once post up a month! Here is mine for February.

My Top 5 iPhone Applications Redux

Posted February 6, 2009 by Greg Martin
Categories: apple, iphone

>Back in july I posted about my top 5 iPhone applications.  I figure it’s been about 6 months and it would be a good time to revisit this topic as my top 5 have since changed.  So in no particular order, here they are…

I managed to pick this app up when it was initially released for free, now it runs $2.99, but I would still pay for it. Zenbe is a pretty straight forward list tracking app that allows you to create multiple lists, assign due dates and organize your items. It has the added bonus of having a pretty decent web front end that stays in sync at lists.zenbe.com

I continue to find Yelp very useful when looking for new restaurants and bars, the iPhone app is a nice compliment to the website.

I am pretty much addicted to iPhone solitaire, this version is great. They have a free version as well, but I think its worth the price for the added game variations you get.

I kinda hate to admit it, but I check Facebook on my phone way more than I probably need to be.

Mint is a great tool for tacking your expenses and investments, the iPhone application makes it even more useful.

Honorable Mentions…

I still thing Evernote is a great tool, I just don’t use is at much as I should.

Shazam is one of the most clever apps I’ve seen. It has been able to identify songs in some pretty poor audio situations.

GasBag crashes way more than a public application should, but I do like the MPG tracking component of the application.

Remote is still a great app for controlling your music from anywhere in your house, even if your house is really only about 750 sq. feet.

Connecting to iPhone Applications via Peer-To-Peer Networking

Posted October 15, 2008 by Greg Martin
Categories: apple, iphone, mac

>I recently found myself wanting to copy some documents to the AirSharing application on my iPhone but I was not able to connect to a Wi-Fi network at the time.

As it turns out, this is really easy to do using peer-to-peer wireless networking, enabling applications like AirSharing or the Apple Remote to connect to your machine regardless of if there is an available wireless network.

Note: This can be done on Windows as well, however, I will only be covering the process on a Mac.

  1. First you need to create a new network on your Mac by selecting your AirPort menu item and choosing “Create Network…”.

  2. Choose a name for your network, and optionally require a password (I would suggest adding a password to restrict access to your machine).
  3. On your iPhone, tap Setttings then Wi-Fi.
  4. Your phone should find the network you just created, tap it and enter your password if you chose to set one up.
  5. Now open AirSharing.
  6. Back on your Mac, from the Finder menu, select “Connect to Server…” (this can also be opened by pressing Command+K on your keyboard).
  7. Enter the address specified by AirSharing for connecting and click “Connect”.
  8. A finder window will open with the AirSharing share and a mounted disk will appear on your desktop.

As I mentioned above, this tip is not limited to the AirSharing application.  Any iPhone application that uses wireless connectivity to interface with your machine, such as the Apple Remote, should work with this method.

Active Directory Role Provider

Posted August 15, 2008 by Greg Martin
Categories: .net, active directory, asp.net, code, forms authentication, microsoft

>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, “Courier New”, Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}

.csharpcode .lnum { color: #606060; }

I’ve been using the ActiveDirectoryMembershipProvider to allow my users to login to a custom ASP.Net site with their AD credentials and it is pretty straight forward. Recently I needed to add more granularity to who can view various parts of the site. I wanted to take advantage of our existing AD groups so I assumed there would be something like an ActiveDirectoryRoleProvider as well. After a little searching, it became clear that wasn’t the case, so I decided to roll my own.

Creating a custom role provider is pretty easy, all you have to do is create a new class and inherit RoleProvider:

public class ActiveDirectoryRoleProvider : RoleProvider{}

You will have to create stubs for all the inherited members. We only need to implement a couple of them to get basic role membership checking. We need to get our AD configuration information out of the Web.Config values, so we’ll create a few properties and override the Initialize method:

private string ConnectionStringName { get; set; }private string ConnectionUsername { get; set; }private string ConnectionPassword { get; set; }private string AttributeMapUsername { get; set; }

public override void Initialize(string name, NameValueCollection config){    ConnectionStringName = config["connectionStringName"];    ConnectionUsername = config["connectionUsername"];    ConnectionPassword = config["connectionPassword"];    AttributeMapUsername = config["attributeMapUsername"];

    base.Initialize(name, config);}

Now we’ll override GetRolesForUser which is the bulk of our implementation. We use the DirectorySearcher class in System.DirectoryServices to query AD for the passed username. We then pull the memberOf property from that user and extract the CN component for each entry as the role:

public override string[] GetRolesForUser(string username){    var allRoles = new List<string>();

    var root = new DirectoryEntry(WebConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString, ConnectionUsername, ConnectionPassword);

    var searcher = new DirectorySearcher(root, string.Format(CultureInfo.InvariantCulture, "(&(objectClass=user)({0}={1}))", AttributeMapUsername, username));    searcher.PropertiesToLoad.Add("memberOf");

    SearchResult result = searcher.FindOne();

    if (result != null && !string.IsNullOrEmpty(result.Path))    {        DirectoryEntry user = result.GetDirectoryEntry();

        PropertyValueCollection groups = user.Properties["memberOf"];

        foreach (string path in groups)        {            string[] parts = path.Split(',');

            if (parts.Length > 0)            {                foreach (string part in parts)                {                    string[] p = part.Split('=');

                    if (p[0].Equals("cn", StringComparison.OrdinalIgnoreCase))                    {                        allRoles.Add(p[1]);                    }                }            }        }    }

    return allRoles.ToArray();}

And finally we need to override IsUserInRole so we can easily check for role membership in code:

public override bool IsUserInRole(string username, string roleName){    string[] roles = GetRolesForUser(username);

    foreach (string role in roles)    {        if (role.Equals(roleName, StringComparison.OrdinalIgnoreCase))        {            return true;        }    }

    return false;}

Here’s the the full code (minus the unimplemented inherited methods):

public class ActiveDirectoryRoleProvider : RoleProvider{    private string ConnectionStringName { get; set; }    private string ConnectionUsername { get; set; }    private string ConnectionPassword { get; set; }    private string AttributeMapUsername { get; set; }

    public override void Initialize(string name, NameValueCollection config)    {        ConnectionStringName = config["connectionStringName"];        ConnectionUsername = config["connectionUsername"];        ConnectionPassword = config["connectionPassword"];        AttributeMapUsername = config["attributeMapUsername"];

        base.Initialize(name, config);    }

    public override bool IsUserInRole(string username, string roleName)    {        string[] roles = GetRolesForUser(username);

        foreach (string role in roles)        {            if (role.Equals(roleName, StringComparison.OrdinalIgnoreCase))            {                return true;            }        }

        return false;    }

    public override string[] GetRolesForUser(string username)    {        var allRoles = new List<string>();

        var root = new DirectoryEntry(WebConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString, ConnectionUsername, ConnectionPassword);

        var searcher = new DirectorySearcher(root, string.Format(CultureInfo.InvariantCulture, "(&(objectClass=user)({0}={1}))", AttributeMapUsername, username));        searcher.PropertiesToLoad.Add("memberOf");

        SearchResult result = searcher.FindOne();

        if (result != null && !string.IsNullOrEmpty(result.Path))        {            DirectoryEntry user = result.GetDirectoryEntry();

            PropertyValueCollection groups = user.Properties["memberOf"];

            foreach (string path in groups)            {                string[] parts = path.Split(',');

                if (parts.Length > 0)                {                    foreach (string part in parts)                    {                        string[] p = part.Split('=');

                        if (p[0].Equals("cn", StringComparison.OrdinalIgnoreCase))                        {                            allRoles.Add(p[1]);                        }                    }                }            }        }

        return allRoles.ToArray();    }}

Add the role provider to your Web.Config:

<system.web>    <roleManager enabled="true" defaultProvider="ADRoleProvider" cacheRolesInCookie="true" cookieName=".ASPXROLES" cookiePath="/"                 cookieTimeout="30" cookieRequireSSL="false" cookieSlidingExpiration="true" createPersistentCookie="false" cookieProtection="All">        <providers>            <clear />            <add name="ActiveDirectoryRoleProvider" connectionStringName="ADConnectionString" connectionUsername="username"                 connectionPassword="password" attributeMapUsername="sAMAccountName" type="ActiveDirectoryRoleProvider" />        </providers>    </roleManager></system.web>

You can then check the roles of your user in code like so:

Roles.IsUserInRole("My Group")

Or control access to entire directories via the Web.Config:

<location path="RestrictedSubDirectory">    <system.web>        <authorization>            <allow roles="My Group"/>            <deny users="*" />        </authorization>    </system.web></location>

Follow

Get every new post delivered to your Inbox.