MENU 

Twelve Years of Photos

August 12, 2019  |    0 comments  |  Site-related

When I was a little kid, my parents made sure that we went on adventures to see the world, or at least the world that they had the time and means to expose us to, which usually meant our home state of Texas. From our home in East Texas, we went to easy-to-reach places such as Dallas and Fort Worth, and more-distant locales, such as Austin, San Antonio, Corpus Christi, Big Bend and the Rio Grande Valley. One of the common denominators of these trips was my late father carrying around his Minolta SRT-101 SLR with the “kit” 50mm lens permanently attached.

I was always fascinated by this mechanical wonder…if you took off the lens and clicked the shutter button, you could see the shutter curtain pop open for a split second. Pushing the lever over to advance the film would reset the curtain for the next shot. Ingenious and incredibly interesting for a little nerdy kid who harbored fantasies of building robots and walking on the Moon.

(Side note: I’ve still never built a robot and my chances of ever visiting the Moon are zero)

The fact that this little metal box with a tube of glass on the front could capture memories was—and still is—amazing to me. I still have thousands of my father’s negatives, awaiting for a time when I can get around to digitizing them before they fade away. I relished every chance he’d allow me to click the shutter button and make another celluloid memory.

By the time high school rolled around, I decided to join the yearbook. The staff was shorthanded and I ended up as a photographer. Or, more-often-than-not, the photographer. I loved spending time in the darkroom, processing film and printing it in the dim glow of the red safelight.

I’d hoped to continue doing photography as a hobby after high school, into college, but the reality of the cost of film, let alone maintaining and stocking a darkroom, precluded that. I took a couple of photojournalism classes just to have some access to a darkroom, but outside of that, I rarely took photos.

Graduation came and went and I started my career as a software developer, always thinking that one day I’d get back into photography. But the cost was always a blocker. Then digital cameras came onto the scene. Pricey at first, with not-so-great quality, I kept waiting for them to get better, knowing that memory cards and hard drive storage would be a lot cheaper than film.

Finally, a bit over twelve years ago, the Canon 400D came out and was in my price range. I dove right in. And I loved it.

Going on adventures to take photos was almost eclipsed by the relaxation and zen brought on by editing the photos on my PC. I quickly maxed out my PC’s hard drive with RAW files…I’d go out on a Saturday morning and not return until late in the evening, my CF cards full and my batteries dead.

I loved taking photos, but what good is capturing images if no one gets to see them?

Since there were few avenues for sharing photos—Instagram wasn’t around yet and Flickr was just getting rolling—I decided to create a photoblog. Photoblogs were big at the time, precisely because a lot of people found themselves in the same situation as myself—lots of photos, no where to display to the world.

My goal at the time was to post a photo every day for as long as I could keep it up. Now, twelve years later, I’m still posting a new photo every day.

A lot has happened in that twelve years. I got married. Changed jobs a few times. Moved around the DFW area. Switched from Canon to Panasonic to Sony. But one thing has been consistent and has kept me sane—posting a new photo every single day for over 4300 days straight.

This year, to celebrate the twelfth year of 75CentralPhotography, I put together a barcode representation of every photo posted from August 12, 2007 until today.

Click to view larger

Each vertical line on this image is a representation of each photo posted to the site, compressed to 1 pixel wide and stitched together via a .NET app I threw together.

I think it’s an interesting artwork on it’s own, but as a visual representation of what twelve years of daily photos looks like, it’s a great visualization of the effort and passion that I’ve put into photography for over a decade.

As for 75CentralPhotography, I don’t have plans to stop posting photos daily, so fingers-crossed that I’ll be able to continue for years-to-come.

Thank you for your support for the last twelve years…I appreciate every one of my followers, fans and visitors.

(If you’re interested, you can read more about my personal photographic history at a post I did several years ago. It’s somewhat out-of-date, as it doesn’t cover the years I spent in the Micro Four-Thirds ecosystem and my subsequent transition (still-ongoing) to Sony, but it’s still informative. Or at least I think it is).

An Eulogy for “The Most-Photographed Dog Ever”*

July 25, 2019  |     6 comments  |  Other Stuff

*Perhaps just a bit of hyperbole

On Wednesday morning, after a sudden illness, we had to make the difficult, but ultimately for-the-best, decision to say goodbye to our beloved Winston.

You may not have known Winston, but if you ever had the chance to meet him, he would’ve loved you instantly. He was like that…he loved everybody, oftentimes with boundless enthusiasm that consisted of cuddles and “kiss attacks”.

We adopted Winston in the Spring of 2010; Laura and I had just gotten married the year before and had moved to a new neighborhood in Addison, Texas, where everyone seemed to have a dog and we wanted to join the club. We thought it over for a while—would we go to a shelter and pick one out? or, would we settle on a breed and find the right dog that way? We never really settled on what we wanted…initially, we wanted something on the small side, preferably female.

One weekend in April, we went out to East Texas to visit my mother and, on a lark, decided to visit the Edom Art Festival. While perusing the arts and crafts, Laura came across the Van Zandt County Humane Society booth and took a look at the dogs, not intending, of course, to adopt. But it was love at first sight, for both Laura and the odd-shaped black, white and grey dog with the gorgeous eyes, long waggy tail and friendly smile. He ambled up to her, gave her a hug with his short little legs and we had to bring him home. Despite not meeting our dog criteria (female and small), he’d chosen to bless us with his unyielding love and we brought him into our lives.

He’d been found on a roadside in the Piney Woods of East Texas, abandoned by some sorry person who didn’t appreciate the treasure they’d lost or, for that matter, appreciate the preciousness of a pet’s life. His shelter name was “Stubby”, on account of his short legs and long body (when he was fully grown, he was exactly four feet from the tip of his nose to the tip of his tail, was maybe 14 inches at the shoulder and weighed somewhere in the 70 pound range). After completing his adoption (and, sadly, causing his foster “dad” to have to retreat to his truck to cry on account of how much he was going to miss “Stubby”), we welcomed him into our tiny family.

Of course, “Stubby”, whilst somewhat apropos, just wasn’t dignified enough for our tastes. So we bequeathed the much-more regal Winston upon him. As mentioned, he was an odd-shaped dog, a mix of perhaps Corgi or Basset and Blue Heeler with a bit of Lab thrown in for good measure. His front legs were shorter than his hind legs, giving him the shape of a dragster (though certainly without the speed). On occasions when he’d run (oftentimes to the chant from Laura or myself of “Fast Dog!”), he’d usually jack knife a bit, his longer hind legs outpacing his front.

At home, he joined our two cats, Miis and Squeaky (sadly, Squeaky left us last year after a long, lingering bout of congestive heart failure, thought Miis is still with us, at the ripe age of 18, too mean to die). While Miis never really interacted with him, Winston loved to try to chew on Squeaky’s ears. At least once, one of the cats had enough of his crap and gave him a good swipe across the nose, but, for the most part, they lived together harmoniously.

Living in the neighborhood we did, in a mid-rise building, we walked him every morning and evening, and often more than that. His friendliness and adorableness soon earned him many friends—both canine and human. Countless times, on their first encounter with him, people would ask “What kind of dog is he?”. Unable to ascertain his exact provenance, my stock answer soon became “We’re not sure…just random dog parts. It’s like they just took whatever parts they had leftover at the dog factory that day and put him together”.

Our weekends typically consisted of rising early and going to the dog park, Winston riding shotgun, his Chewbacca to my Han Solo. At the dog park, Winston always seemed to be more interested in the people than the other dogs. He’d make his rounds, greeting everyone with either a smile or, if you were lucky, kisses. He loved to snake along the fence of the park, taking in all the various smells and, I imagine, making a mental map of the most-foul ones for later reference (for reasons that he never revealed). If he felt like playing, he’d wander the grounds, inspecting each and every tennis ball until he found the most disgusting one, just to make sure that I had to touch something I’d rather not. After leaving the dog park, we’d go through the local drive-through car wash…Winston loved the sights and sounds of the water and soap jets cleaning the car. If we were feeling a bit peckish, we’d swing by the donut shop for breakfast…a donut for me, a dozen donut holes to take home to Laura and a donut hole treat for Winston.

In the evenings, Laura and I would watch TV, Winston curled up on the sofa between us. On occasion, I’d make a cup of coffee, set it on the end table and leave the room for a moment, only to return to find an empty cup and a slightly-jittery dog. As the months passed, it became apparent that Winston was one of the most-important parts of our lives. Without kids, we focused our love on “Sweet Winnie”. We dressed him up as a pirate for a pet costume contest, we bought him sweaters to keep him warm in Winter (he loved wearing clothes) and we took him on adventures. We were “dog people”.

The first time we traveled out-of-state after adopting him, we were forced to board him at a local pet hotel and, I’m not-to-ashamed-to-admit, I cried on the way there and back, unable to bear to leave him, worried that he might think we didn’t love him and were abandoning him like he’d been abandoned as a puppy. Each time after that, it got a bit easier to leave him, but every vacation’s last few days would be punctuated by Laura or myself exclaiming “I’m so ready to get home and see Winnie”.

After a few years, Laura left her job teaching and started traveling for work, oftentimes being gone for three weeks out of the month. Luckily, I always had Winston with me to keep me company. We’d have long, one-sided conversations with Winston always being a good, patient listener. To wile away the time while Laura was out-of-town, we’d watch obscure movies (usually in a foreign language, which I assumed perturbed Winston as he couldn’t read the subtitles) or work on software or photography projects. At night, he’d climb into bed with me, his collar’s tags clinking in the darkness (I’d usually take it off at night, saying “Let’s take off your jingle-jangle, Winnie”), and curl up next to me. On Winter nights, his prodigious body heat was welcome, staving off the cold that the heater couldn’t. On Summer nights, I’d have to turn the ceiling fan and the tower fan on full blast just to get comfortable. When Laura was home, he’d do the same, though we’d often need to move him a bit to get it comfortable for all three of us (he never really learned to lay parallel, preferring a perpendicular arrangement to ensure that he could touch both of us at the same time.

A few years ago, Laura was diagnosed with cancer and needed to undergo both chemotherapy and radiation treatment. Winston never left her side—for three straight months, he slept on her feet at night to keep her warm, snuggled her when she was restless and loved her when the chemotherapy’s effects were at their worst. Many nights, I turned to Winston for love and comfort as I struggled to stay strong for Laura while we went through this experience. He never not loved me back…a steady source of comfort, strength and loyalty.

Eventually, we moved into a house to give him the opportunity to have a yard of his own—his own private dog park. He loved to lay out in the sun, soaking up the warmth and relaxing in nature. Worried that he was lonely, we adopted a companion for him a couple of years ago. Millie loved to try to get him to wrestle and play, but they usually just settled with lying together in the yard or climbing into bed with us at night, a half-human/half-canine dog pile. Millie was, at most, only a few months old when we adopted her and our hope was that, although he was getting to be “comfortably middle-aged”, Winston would have several more years to teach her how to be a “good dog”; a selfless, loving, friendly companion. And though it’s taken a couple of years, I’d say he succeeded. Millie, while being full of boundless energy—the polar opposite of Winston—is also full of boundless love.

Roughly a year ago, we took in our “old lady”. Bonnie’s owners were forced to let her go when they were moved into a nursing facility. At eleven-years-old, we knew no one else would adopt her and we decided that the right thing to do would be to bring her into our home and let her have the best life possible for her remaining days. Unfortunately, we soon discovered that she was heartworm positive, so those days might go quick. Winston and Bonnie got along well; while old and sickly, Bonnie loves to play with Miilie and Winston would often try to impose himself on their wrestling matches. A couple of months ago, however, we were informed that her disease has progressed to the point where she might have “weeks to months” to live. We knew our time with her would be short, so we’ve been somewhat-prepared for the day when we have to say goodbye to her.

We never thought we’d be saying goodbye to Winston before Bonnie. Though he’d been arthritic for a couple of years now, having a hard time getting around, he’d been otherwise energetic and playful. And now, suddenly, in the last week, he was sick. Coughing, struggling to breath and barely moving. Our first vet visit on the weekend judged him to have nausea and upset stomach, but by the next night, he was doing worse. Coughing, trying to throw up and struggling. We took him to another vet, referred by his primary vet, who judged that he had developed a rare condition (megaesophagus) and would have to be hand fed while sitting up for the rest of his life and the prognosis wouldn’t be good. Drugs were prescribed and attempts were made to get him to eat, but his condition kept deteriorating. On Tuesday, we took him to the ER and they told us his prognosis wasn’t not great at all, but that there was a chance he might turn around a bit and that we could give him palliative care for a few days to make sure he was comfortable. They’d keep him overnight and give him steroids and fluids. We gave him loves and went home, wondering if we’d made the right choice.

By Wednesday morning, the vet had called and let us know that he’d made a sharp turn for the worse. Knowing there was nothing we could do to make him better, we made the hard, too-short drive to the hospital to say our goodbyes and help him pass on to the next life. 

We just hope that he knew that we loved—and will always love—him and that were ultimately doing this to make things better for him. He wouldn’t be in pain any longer and wouldn’t needlessly-suffer. We both held him as he took his last breaths and I’m certain that he knew we loved him.

I like to think that Winston had so much love to give that he gave it all away a bit too quickly. We’ll be forever grateful that he was part of our lives and I’ll cherish my time with the “odd-shaped dog” for the rest of my life. If there is a better place or afterlife for dogs, I like to think that Winston is there now, sniffing around for the best smells, gently taking the tastiest treats and finally conquering his irrational fear of snowmen.

Luckily, for us, we have an incredible photographic archive of our life with Winston. Looking through my Google Photos and Lightroom catalogs, I’d say that there are roughly 20,000 photos of him taken over the years. Over the last day, it’s been both joyful and heartbreaking to scroll through these digital memories, many of which reminded me of several of the anecdotes I shared in this piece.

Master of the “side-eye”

Looking sad on his first visit to the vet

We took him to visit Santa for his first birthday. Since he was about four-months-old when we adopted him in April 2010, we celebrated his birthday on Christmas Day.

A rare display of athletic prowess as Winston attempts to catch a snowball
Winston never had a sad day in his life…he was always smiling
Showing some concern
Love, Always and Forever
(Adapted and expanded from a post I made on Facebook on July 24th, 2019)

My Geo-Tagging Workflow

February 28, 2019  |    0 comments  |  Apps GPS Logs Technique/Workflow

In my last post, wherein I outlined how I added a link to each photo’s location on Google Maps, I mentioned that I thought I’d done a writeup on how I geo-tag photos, but couldn’t find it. After extensive searching of the archives, I can confirm that I don’t seem to actually have ever written about my process. Today, I’ll rectify that oversight.

Let’s take a look at the tools I use, then I’ll walk you through how it all comes together.

First, we need a way to record a GPS log. Typically, these are in the format of a .gpx file, which is a type of XML file that can contain a geotrack, which is, at its most-basic, a series of GPS fixes in latitude and longitude along with a timestamp for each point that allows software to reconstruct a route. It may also, but not necessarily, contain speed and heading information. It can also contain a series of waypoints, which are GPS fixes that aren’t linked in a time dimension, so no track can be generated from these as there’s no way of knowing which order the GPS fixes/points were gathered, as order in the file doesn’t necessarily mean that’s the order they were gathered. In addition, we’ll need the time information later to match the time a photo was taken to a spot on our geotrack.

To build a .gpx file while out taking photos, we need a GPS receiver that has the ability to periodically record our current location in a file then export it for consumption by another tool to actually tag the photos. For this, I use a couple of different tools:

When I was using an iPhone as my day-to-day phone, I used an app called MotionX GPS to record my tracks.

Now that I’m using a Google Pixel 2 XL as my phone, I’ve had to find a different app to record tracks as MotionX GPS isn’t available for Android. I tried a few an eventually settled on GPSLogger. The UI isn’t as pretty as MotionX GPS, but it gets the job done.

The next tool we need is a way to merge the location and time data in our .gpx file with our photo data. Since I’m an Adobe Lightroom user (Classic, none of that CC nonsense for me!), I could use Lightroom’s rudimentary built-in geo-tagging feature (a tutorial can be found here), but I prefer some fine control over the process, so I use Jeffrey Friedl’s excellent Geoencoding Support plugin.

This allows us to fine-tune all sorts of fiddly bits in the process, such as correcting for the camera’s time being off a bit from the actual GPS time, which brings us to our next point:

How do I ensure that my time is correct on my camera?

There are a few ways to do it. If you’re lucky, your camera’s companion smartphone app supports synchronizing your phone’s time with your camera’s time, such as the Panasonic Image App (Android/IOS) does. If you’re not-as-lucky, you have to manually sync it, which means opening your camera’s settings and setting the date/time to match the phone’s as close as possible. Fortunately, it doesn’t need to be precise as most geotagging tools, such as Jeffrey’s Lightroom Geoencoding Support, allow for some “fuzziness” to the time matching algorithm.

Once you’ve tagged your photos, you can manually tag any misses in Lightroom’s Map tab. Now you have a precise log of your adventures and the photos you’ve taken.

In addition, you can open the .gpx file in Google Earth and get a nice map of your adventure. Here’s one from a visit I made to the Great Smoky Mountains last year:

So, there you have it, my geotagging workflow. However, I would be remiss in failing to mention that I’m currently testing using a GPS watch (the Suunto Traverse) for tracking as I don’t need to worry about killing my phone’s battery life while logging my location. So far, so good. I might do a write up in the future about my experiences with it.

How I Added Photo Location Data to 75CentralPhotography.Com

February 17, 2019  |    1 comment  |  Code GPS Logs Site-related

I like to geotag my photos. Almost every time I go on a phototrek/drive/adventure/walk, I log my locations so that I can merge my geotagged data with my photos and know exactly where each photo was taken. (I swear I thought I’d done a write-up on how I do this, but I can’t seem to find it. I have posted some of the track logs in the past however…you can see them here .)

Since I have this data sitting around and it’s embedded in each photo on 75CentralPhotography.Com, I thought it would be fun for visitors to the site to see exactly where in the world each photo was taken. But how to do this?

WordPress—the backend system for the site—helpfully provides a function to store EXIF data (basically the metadata in a photo that shows interesting things like shutter speed, aperture, ISO and a ton of other stuff) but only stores the basics, whereas the EXIF standard has scores of datapoints (colorspace, exposure bias, YCbCr positioning—whatever that is—to name a few). Unfortunately, this means that they don’t include location data as part of this limited scope.

Luckily, some kind soul has already solved part of the problem for us with a built-in function in PHP (WordPress’ programming language). This function, exif_read_data(), will let us read any part of a photo’s EXIF data and use it how we want. In this case, that would be to link to Google Maps and show a place marker of where the photo was taken.

Here’s how I leveraged that function to add a link on each photo’s page to the related location on Google Maps.

First, we need to get the photo’s EXIF data. Since exif_read_data() will only accept a local file as a parameter, we need to get the local path to the image relative to the page where we are executing the code/displaying the link. Fortunately, WordPress has us covered with a couple of functions: attachment_url_to_postid() and get_attached_file().

attachment_url_to_postid takes the URL of an attachment (i.e. a photo attached to a post) and returns the ID of that photo. To get the attachment’s URL, we use our old friend catch_that_image(), which resolves the URL of the first photo on a post (and, since we only ever post one photo at a time on the site, the only image on a post). Then, we take the result of that function and pass it to get_attached_file(), which returns the aforementioned local path of the photo file:

$attachment_id = attachment_url_to_postid( catch_that_image() );
$fullsize_path = get_attached_file( $attachment_id ); 

We then take this local path and pass it to exif_read_data() for parsing of the photo’s EXIF data:

$exif = exif_read_data($fullsize_path);

This function returns an array of values where the first value is the EXIF data label and the second is the EXIF data itself (you might think of this as a keyset). So, a particular photo’s data might look something like this:

KeyValue
Equipment Make SONY
Camera Model ILCE-7RM2
Camera Software Adobe Photoshop Lightroom Classic 8.2 (Macintosh)
Photographer Matt Harvey
Maximum Lens Aperture f/2.8
Focal Length (35mm Equiv) 44 mm
Horizontal Resolution 96 dpi
Vertical Resolution 96 dpi
Image Created2019:02:16 21:03:14
Exposure Time 1/80 sec
F-Number f/4.5
Exposure Program Normal Program
ISO Speed Rating100
Lens Aperture f/4.5
Brightness 7.2 EV
Exposure Bias 0 EV
Metering Mode Pattern
Light Source Unknown
Flash No Flash, Compulsory
Focal Length 44.00 mm
Color Space Information sRGB
Exposure Mode Auto
White Balance Auto
Scene Capture Type Standard
Contrast Normal
Saturation Normal
Sharpness Normal
Latitude N 33° 3.9174′
Longitude W 96° 58.2118′
Resolution Unit i
Exif IFD Pointer266
Compression Scheme JPEG Compression (Thumbnail)
Horizontal Resolution 72 dpi
Vertical Resolution 72 dpi
Resolution Unit i
Offset to JPEG SOI1044
Bytes of JPEG Data19487
Exif Version2.3
Image Generated2019:02:16 07:52:16
Image Digitized2019:02:16 07:52:16
Shutter Speed 1/80 sec
Focal Plane Horiz Resolution 2164 dpcm
Focal Plane Vert Resolution 2164 dpcm
Focal Plane Res Unit cm
File Source Digital Still Camera
Scene Type Directly Photographed
Digital Zoom Ratio1
GPS Info Version 2.2.0.0
Latitude Reference N
Longitude Reference W

In the context of this project, we only care about two elements of this data: Latitude and Longitude. So, to extract individual data points, we use a couple of functions to extract the coordinates and convert to decimal:

$lon = getGps($exif["GPSLongitude"], $exif['GPSLongitudeRef']);
$lat = getGps($exif["GPSLatitude"], $exif['GPSLatitudeRef']);

Which calls:

function getGps($exifCoord, $hemi) {
	$degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
	$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
	$seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
	$flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1;
	return $flip * ($degrees + $minutes / 60 + $seconds / 3600);
}
function gps2Num($coordPart) {
	$parts = explode('/', $coordPart);
	if (count($parts) <= 0)
	return 0;
	if (count($parts) == 1)
	return $parts[0];
	return floatval($parts[0]) / floatval($parts[1]);
}

So we finally have a specific photo’s GPS location. Our final step is to verify that we have valid data for GPS (i.e. neither the latitude or longitude are 0, because that’s what’s returned when no GPS data is available and there could be, but shouldn’t be, photos on the site without location data). If the verification passes, we link to Google Maps with our coordinates:

if($lat <> 0 && $lon <>0){
								echo '<a href="https://www.google.com/maps/search/?api=1&query='.$lat.','.$lon.'" target ="_blank" title="Location data may be innacurate or fuzzed in certain cases">View This Photo\'s Location on Google Maps</a></br>  ';
							}

Note that we added a title element to the anchor tag for the link that states that photo data may be inaccurate or “fuzzed” for some photos. This is because some photos were tagged “after the fact” instead of using an actual GPS log or were tagged en masse with a fairly-accurate location or were tagged with a general location to preserve privacy (i.e. photos I’ve taken at home or other people’s homes).

To view any photo’s location on the site, go to the individual page for a photo and click the “View This Photo’s Location on Google Maps” link under the photo’s tags.

If you find any bugs or photos without GPS data or have any ideas for improvements, please let me know at matt@75central.com.

Even More Nerdiness

February 12, 2019  |    1 comment  |  Apps

Last week, I wrote about a simple Windows app I built to automatically set my Windows 10 wallpaper to a random photo from 75CentralPhotography.Com. This week, I ran into another issue/want/need that required me to once again dust off my Windows development skills to solve.

I thought it would be nice if all my Chromecast-connected TVs and my Google Home Hub would display my photos as part of their screensaver feature. However, to do this, I’d need to have a folder in Google Photos of all my published photos. Building this collection of photos is actually a bit harder than it sounds, believe it or not! Why not just export all of the photos from your Photoblog collection in Lightroom?, you ask. Well, the problem there is that that collection actually contains about 600 other photos that have either not been published or were mistakenly tagged as a photoblog item, so any export would have a lot of cruft. So, I needed a way to get all of the photos. Downloading from the backend of 75CentralPhotography.Com was also an option, except that there’d be a lot of extraneous files there as well for a couple of reasons: 1) since the site runs on WordPress, any time an image is uploaded, WordPress helpfully generates a few versions of the file in addition to the original for thumbnail and featured images and, 2), there are leftover files from revisions to posts, so for any photo I’ve ever re-edited and republished, there’s the old version lurking about. Also, a few years ago, we painstakingly re-edited each post to upsize the photos to more-pleasing, easier-to-appreciate dimensions, so the previous versions are out there as well.

To solve this, I decided that I could reuse a lot of the code I’d written for the previous wallpaper project and build a couple of items:

  1. A new RESTful API that would return the photo from a particular date presented to it.
  2. A Windows application to iterate through every day since we started publishing photos (August 12, 2007) until the present day, calling the aforementioned webservice and downloading the photo that was returned by the service.

To accomplish the first step, I made a copy of the code from the webservice built for my previous project and modified it expect a date query string parameter, so calling the service looks something like this:

{base URL}/photodate/?date=12/14/2018

The webservice parses the date element into three strings for month, day and year and adds them to an argument array for WordPress’ WP_Query() function:

$datep=  $_GET['date'];
$pieces = explode("/", $datep);

  $args = array(
      'date_query' => array(
          array(
              'year' => $pieces[2],
              'month' => $pieces[0],
              'day' => $pieces[1]

          )
      )
  );
$your_query = new WP_Query( $args );

WordPress automatically performs the query, and if results are returned, assigns the results to variables:

if($your_query->have_posts()){
  while ($your_query->have_posts()) :
    $your_query->the_post();
    $imageurl= catch_that_image();
    $permlink = get_post_permalink();

  endwhile;
}

We use the catch_that_image() function again to get the URL to the first (and, in our case, only) image in the post. We then serialize this into a JSON string and return the results:

{"Image":"http://www.75centralphotography.com/wp-content/uploads/2018/12/las-vegas-bliss-dance-sculpture-hand.jpg","permalink":"http://www.75centralphotography.com/?post_type=post&p=38007"}

Moving on to the Windows app part of the solution, I built a simple UI that would let me choose a start date, choose a folder to save the images to, and a button to actual start the process:

On the backend, clicking the Process button calls this bit of code:

 Dim startdate As Date = Me.DateTimePicker1.Value.Date()
        Dim today As Date = Date.Now()
        Dim i As Integer
        Dim wo As New WebOps
        Dim rP As Bitmap
        Dim currUrl As String
        While startdate <= today
            currUrl = wo.getURL(startdate)
            rP = tempPB(currUrl)
            rP.Save(Me.FolderBrowserDialog1.SelectedPath & "\" & i & ".jpg", Imaging.ImageFormat.Jpeg)
            i = i + 1
            startdate = startdate.AddDays(1)
            Application.DoEvents()
        End While

First, we declare our variables and objects:

  • today is obviously today’s date and sets the upper bound of possible days that images have been published
  • i is the counter for how many times we’ve looped through the download process (we also use that to build our filenames so that our output is a nicely-ordered list of published photos in order of published date
  • wo instantiates a copy of a class I built called WebOps, which does the heavy-lifting of calling the webservice and returning the results
  • rp is a Bitmap object, basic a blob of data that represents our image file that we’ve downloaded
  • currlURL represents the URL we’re calling, in this case, the base URL for the service with the date parameter appended

Next, we start the actual processing:

  • We wrap everything in a while loop. This loop starts at the date chosen in the datepicker control on the user interface and iterates through each day until today by adding a day to startdate on each pass through the loop.
  • We first set the value of currUrl by calling the getURL function in the WebOps class:
        Dim format As String = "MM/dd/yyyy"
        Dim fdate As String = getdate.ToString(format)
        Dim url As String = baseURL & "?date=" & fdate
        Dim wc As New WebClient
        Dim jRes As String
        wc = New WebClient
        Dim retry = True
        While retry
            Try
                jRes = wc.DownloadString(url)
                retry = False

            Catch
                retry = True
            End Try
        End While
        Dim tempPost = New With {Key .Image = ""}
        Dim post = JsonConvert.DeserializeAnonymousType(jRes, tempPost)
        Dim com As String = post.Image
        Dim tempURL = New With {Key .permalink = ""}
        Dim pURL = JsonConvert.DeserializeAnonymousType(jRes, tempURL)
        Dim plink As String = pURL.permalink
        Dim u As New utilities
        wc = Nothing
        Return com

This returns the URL of the photo posted on the specific date passed into the webservice (you’ll notice that we also get the permalink, but we don’t use it…this is simply because I reused this code from the wallpaper app).

  • We pass the currUrl into the tempPB function, which does the work of downloading the image and setting its data to the rp bitmap object
Private Function tempPB(url As String) As Bitmap 
        Dim tClient As WebClient = New WebClient
        Dim tImage As Bitmap = Bitmap.FromStream(New 
           MemoryStream(tClient.DownloadData(url)))
        Return tImage
End Function
  • Then we save rp to disk as a .jpg file, targeting the folder chosen in the user interface and using the value if i as the filename.
  • We then increment our startdate value and i‘s value
  • Finally, we through in a call to Application.DoEvents(), which is a simple, though not-necessarily-the-best, way to ensure that the application’s interface doesn’t freeze while in a loop.

When the application runs, it iterates from the chosen date to today and saves the files locally. When it finishes running, which is in the case of starting on August 12, 2007 and ending today, we end up with a folder of of over 4200 ordered .jpg files of every published photo on 75CentralPhotography.Com:

To get these into Google Photos for casting to Chromecast devices, we create a folder in Google Photos and upload:

Finally, we hop into the Google Home app and set the album as the source of images for the Chromecast’s Ambient Mode:

More Nerdiness

February 8, 2019  |    1 comment  |  Apps

As you may or may not know, in addition to taking fine photos, I enjoy designing and building software. For the last several years, I’ve been working in the cloud, mainly on the Force.Com platform, but before that, I was a Windows developer. Occasionally, I like to build a little software project on my own just to make sure I can still develop desktop applications or to build little tools to make my life easier. I did this much more often when I was a strictly-Windows guy, but since moving to an iMac as my desktop machine for day-to-day use and post-processing, I don’t get to do it as often as I’d like as I haven’t the time to learn Objective-C or Swift. Luckily, to sate my need for Windows-related development, I have a Windows 10 Virtual Machine on my iMac running under Parallels as well as a Dell XPS laptop.

For my latest “me project”, I thought it would be cool if I could have my Windows desktop wallpaper periodically change to one of the photos on 75CentralPhotography.com. To accomplish this, I knew I’d need a couple of pieces of software running in different places:

  1. A webservice or some other means of fetching a random photo from the site
  2. A local application running on Windows that would periodically make a call to the aforementioned webservice and get the random photo

So, for the first part, I build a RESTful API on 75CentralPhotography.Com that looks for photos on the site that I’ve specified as wallpaper candidates and returns one at random. Since our site runs on WordPress, a lot of the functionality was already in place. The process works like this:

  1. A new post custom metadata field called 75Wallpaper was created that can be set to TRUE if that photo should be used as wallpaper.
  2. A new webservice was written in PHP that uses WordPress’ WP_Query method to return a random photo with the above criteria
    $args = array( 'meta_key' => '75wallpaper', 'meta_value'=>'TRUE', 'posts_per_page' => '1', 'orderby' => 'rand' ); $your_query = new WP_Query( $args ); if($your_query->have_posts()){ while ($your_query->have_posts()) : $your_query->the_post(); $imageurl= catch_that_image(); $permlink = get_post_permalink(); endwhile; } 

    We use a handy function I found on the web some time back called “catch_that_image” that grabs the URL of the first image on a post, which ensures we get the link to the image. We also go ahead and grab the permalink to the image.

  3. We then serialize these results into some JSON so that making a call to this service results in a response that looks like this:
    {"randomImage":"http://www.75centralphotography.com/wp-content/uploads/2018/05/tandy-hills-nature-area-sunrise-grass-fort-worth.jpg","permalink":"http://www.75centralphotography.com/?post_type=post&p=36891"} 

Now to build the Windows portion. For this, I chose to build a .Net application in VB.Net, however, I could’ve just as easily used C#.

To start, I created a simple UI with a couple of buttons and a picture box. One button would let the user interactively set a new background by calling the above webservice’s randomImage element and the second would use the permalink element to open the current wallpaper’s page on 75CentralPhotography.com in the default browser. The picturebox would display the current wallpaper and was really just there for testing purposes (i.e. I needed to ensure I was retreiving the image properly before I wrote the code to set as the wallpaper).

I then started writing some code to do the magic.

  1. First, I needed to build a function to call the webservice and retrieve and store the results, including downloading the image to the Windows AppData folder:
Public Function ProcessWallpaper() As Boolean
        Dim wOPs As New WebOps
        Dim AppDataPath As String
        Dim u As New utilities
        Dim doesAppDataPathExists As Boolean
        Dim rP As Bitmap
        Dim setSuccess As Boolean
        Dim randomfilename As String = u.createRandomFilename()
        rP = tempPB(GetRandomImageURL()) ' fill form picturebox for testing
        AppDataPath = u.getAppDataPath()
        doesAppDataPathExists = u.checkfolderexists(AppDataPath)
        If doesAppDataPathExists Then
            rP.Save(AppDataPath & "\75Central\" & randomfilename, Imaging.ImageFormat.Jpeg)
        End If
        setSuccess = u.setWallPaper(AppDataPath & "\75Central\" & randomfilename)
        wait(5)
        ClearAppData(AppDataPath)
        Return True
    End Function

This code is called in three places:

  1. When the application loads, immediately setting a new wallpaper
  2. When the “Set New Wallpaper Now” button is clicked
  3. Every ten minutes after the application starts running, ensuring that a new wallpaper is set on a regular schedule

2. Secondly, I needed some code to actually set the wallpaper. Luckily, .Net already has a function to do this, so I just needed to call it and pass the path of the image downloaded:

Public Function setWallPaper(imagefile As String) As Boolean
        SystemParametersInfo(SETDESKWALLPAPER, 0, imagefile, UPDATEINIFILE)
        Return True
    End Function

3. Finally, I needed to cleanup the download. Once a Windows 10 wallpaper is set, it’s stored internally in the operating system and no longer needs to persist as a separate file, so there’s no reason to have a high-res version of my photo hanging around on my PC, taking up space:

Private Sub ClearAppData(apppath As String)
        Dim directoryName As String = apppath & "\75Central\"
        For Each deleteFile In Directory.GetFiles(directoryName, "*.jpg", SearchOption.TopDirectoryOnly)
            File.Delete(deleteFile)
        Next
    End Sub

All of this code is tied together to work, and upon launch, the app nicely minimizes into the system tray out of the way until the icon is double clicked to show the UI

So, there you have it, my latest nerdy project. If there’s sufficient interest, I might release this as a free download so that you can have automated new fun wallpapers. If you’re interested, shoot me an email at matt@75central.com!

My Most-Interesting Photos of 2018*

December 31, 2018  |    0 comments  |  Site-related
*Once again, according to Flickr’s dubious and mysterious “Interestingness” algorithm.

As I’ve done in past years, I thought I’d share the 10 most-interesting photos from 2018 that I published on 75CentralPhotography.Com. To figure out what are the 10 candidates, we rely on Flickr’s “Interestingness” algorithm, which doesn’t actually seem to work very well, as I feel like I’ve published a lot of other photos that are more interesting than those chosen by Flickr. Oh well…here you go:

1.

On the Engine’s Edge

40982336240_3833756a9b_o

2.

Under the Stripes

25071947087_74d05618f2_o

3.

Celine

40090861275_e18b492ac1_o

4.

BALLYS

38488365990_17020d416c_o

5.

Big Boulders

40761537792_3c13476558_o

6.

Last Sun on the Power Lines

40921989060_7350bb093b_o

7.

Big Tree

27882386457_a28afc5389_o

8.

Stairs and Rails

Maker:0x4c,Date:2017-10-20,Ver:4,Lens:Kan03,Act:Lar01,E-Y

9.

LOVE

41228805141_1008494011_o

10.

Glowing Orbs

40201542871_c32d65a0ac_o

Passive Income from Piracy

December 15, 2018  |    0 comments  |  Legal Rights

If you’re like me and share your photos online in any capacity, you’ve probably had at least a few stolen by unscrupulous people for use on their websites or for other promotional reasons. Usually, you’d deal with this by finding the violator and either sending an invoice or filing a DMCA takedown. Unfortunately, in my experience, invoices sent generally mean invoices ignored. Of course, you could always hire a lawyer to go after copyright thieves, but that usually takes upfront capital, which can mean a fair amount of money out-of-pocket with no guarantee of a reward. And running down copyright violators on your own can take a lot of energy and time.

Time and energy that I don’t have. Nor do a lot of people.

So, what do I do about copyright thieves?

I recently discovered Pixsy.Com, a service that searches the web for violations, lets you choose the ones worth pursuing via their service, and goes after these for resolution.

It’s pretty easy to use and doesn’t take a lot of time or effort. Once you’ve signed up, you can sync your Flickr, SmugMug, Instagram or other social accounts or upload a batch of photos.

They then periodically scan the web for uses of these photos and present potential matches in an easy-to-use interface for you to browse.

Pixsy___Matches.png

From here, you can reject false-positives, confirm if the use of a photo is okay or submit a case.

When you submit a case, you provide some background information on the image, such as when and where it was taken as well as when you first published it on the web, and Pixsy goes to work. They evaluate your submission for feasibility of pursuing based on whether or not they feel it will result in payment as well as if the amount of payment is worth the effort.

If the image is accepted into the resolution program, they contact the violator via email, presenting them with documentation of the violation as well as an invoice. If this is ignored, they eventually start calling the violator until they get resolution. If they don’t get a response from a thief, they will consult with their associated legal firms as to whether or not it’s worth filing suit.

If they get resolution, they keep 50% as their fee, which might seem high, but I think it worth it for me not to have to mess with.

And it’s been pretty worth it for me. In the few months I’ve been using their service, I’ve netted of $4000 in fees for only a few hours of my time. And while direct licensing of there photos would’ve made me more if the violators had actually bothered securing a license instead of offering their usual excuses (“my web guy did it” or “I found it on Google Image Search, so I thought it was free”), it’s more than I would’ve made had I tried to do this on my own (which would be $0 because I’m a) busy, b) lazy and c) don’t have a law firm with which to send scary letters on my behalf).

The one caveat I have, however, is that Pixsy only operates in certain countries. So they’ve been unable to hunt down Metallica’s thievery of one of my photos because the record label that actually published the CD with the violation is based in Greece, outside of their operating area. To resolve this, I am looking at other legal options.

 

Pixsy___Matches___amazon_co_uk__2_.png

So, if you’re a photographer who doesn’t have time or energy or money to pursue pirates on your own, I highly-recommend giving Pixsy a try.

© 1993-2019 Matt Harvey/75Central Photography - All Rights Reserved • Contact license@75central.com for image licensing and other queries.