Skip to content
wtblock edited this page Jul 5, 2026 · 17 revisions

PhotoLegacy Suite

I am offering this software to anyone interested in preserving their family history as I have done using this program. Please be aware that, as this is not commercial software, it has not undergone extensive testing. To be precise, the only testing conducted thus far has been on my personal computer, specifically a Surface Laptop 7 with an Intel processor running Windows 11.

A Note of Caution

In the medical field, professionals adhere to the Hippocratic Oath, which includes the principle, "First do no harm." Applying this philosophy to the preservation of our family's photographic legacy, I recommend never working directly on the original images. Instead, copy your photographs to a designated working folder, as I will explain below. Should an error occur, only the copy will be affected, leaving the original intact. It is a common misconception that working on a cloud drive constitutes a backup; however, the cloud functions more like a mirror. If an incorrect file is accidentally copied over one of your images, the cloud will synchronize and replicate this change. Therefore, it is advisable to always perform your work on a local drive.

The PhotoLegacy solution is a multi-application system for organizing, indexing, exploring, and printing a large family photo archive.

It consists of:

  • BuildPhotoIndex – Scans folders and builds/incrementally updates an inverted index of file paths and comment metadata.
  • QueryPhotoIndex – Command-line tool that queries the index to do searches and can supply a dump of the index for debugging.
  • PhotoExplorer – MFC application for browsing folders, photos, and viewing/editing metadata and creating labeled versions of those photographs.
  • PhotoPrinter – Tool for generating high-resolution photo albums based on folder ranges, metadata, and optional queries.
  • Common Library – Shared code for index I/O, metadata structures, and utility classes.

PhotoLegacy is a Visual Studio 2019 solution.

Introductory YouTube Video

2026.07.02 Photo Legacy Introduction

Accessing Photo Legacy

2026.07.01 Accessing Photo Legacy

Folder Structure

First a YouTube video describing how to setup a demonstration workspace:

2026.07.01 Organizing Photo Legacy Workspace

The following is an example of a working folder:

  • Legacy (working folder)
    • BuildPhotoIndex.cmd (command to launch BuildPhotoIndex.exe to maintain the working folder)
    • PhotoExplorer.cmd (a command to launch the Photo Explorer application)
    • PhotoPrinter.cmd (a command to launch the Photo Printer application)
    • QueryPhotoIndex.cmd (a command to launch the QueryPhotoIndex.exe)
    • SynchPhotos.cmd (a command to mirror changes to backups like the cloud and/or an SSD)
    • Block Family Ancestors.pp (a sample book document)
    • 1800 to 1970 A -- Block Family Ancestors (book folder)
      • 1800 (entire century because there are so few photographs)
        • 1846.04.01 Bark Constitution (an album)
          • Labeled (a subfolder for copies of the folder images that have been labeled, the original image appearance is unchanged)
            • 1846_04_01_19_06_34.jpg (a single image was labeled in this example)
          • 1846_04_01_14_50_33.jpg (an image member of the album with updated metadata, but not copied to the labeled folder)
          • 1846_04_01_18_55_56.jpg (images like this that are not copied to the labeled folder are not included in books)
          • 1846_04_01_18_57_28.jpg (they may represent original copies with handwritten notes for example)
          • 1846_04_01_18_59_28.jpg
          • 1846_04_01_19_06_34.jpg (the only image that was copied to the Labeled subfolder that will appear in the book)
        • ... (more albums)
        • \1898 Neltje Rienstra (Nell) Koelemay (final album of the century)
          • 1898_01_01_22_02_33.jpg
          • Labeled (a subfolder for copies of the folder images that have been labeled, the original image appearance is unchanged)
            • 1898_01_01_22_02_33.jpg (the one and only image was labeled in this example)
      • 1900 (a decade of photographs)
      • 1910
      • 1920
      • 1930
      • 1940
      • 1950
      • 1960
      • 1970 A
    • 1970 B to 1980 A -- Our Early Years (next book folder)
    • ... (additional book folders)
    • Books (a folder containing the exported books)
    • PhotoIndex.phix (the binary index of the labeled photographs used to build books)
    • bin (a folder of the executables)
      • BuildPhotoIndex.exe (command line program to build / incrementally update the index)
      • PhotoExplorer.exe (a desktop application to enter the metadata describing the images and album)
      • PhotoPrinter.exe (a desktop application to generate books from the labeled images)
      • QueryPhotoIndex.exe (a command line program to test and debug the index)
      • mfc140enu.dll
      • mfc140u.dll
      • msvcp140.dll
      • vcruntime140.dll
      • vcruntime140_1.dll

The bin folder is a working deployment folder under the working folder root, containing EXEs and runtime DLLs. The working folder contains command files that point to the executables in the bin folder to ensure the applications are running in the root folder containing the folders of photographs.

This is important so documents to create books can use relative paths to allow the data to be backed up to SSDs and cloud storage and not be tied to absolute pathnames.

Folders and images (JPG only) are labeled using year, month, and day at the beginning of the names so that sorting becomes chronological. Years are four characters and month, day, hours, minutes, and seconds are two characters. Once the date taken metadata is filled in by PhotoExplorer, there is a toolbar button to rename the image in the format shown above based on the date taken. Old, scanned images have to populate date taken manually, but recent digital images will have this data populated by the camera.

The 1800 to 1970 A -- Block Family Ancestors folder tree illustrates how photographs should be organized for creating books. The Block Family Ancestors.pp file is a book document for the Photo Printer application. When you open the file with PhotoPrinter, there are three folders defined:

  • Start Folder is .\1800 to 1970 A -- Block Family Ancestors\1800
  • End Folder is .\1800 to 1970 A -- Block Family Ancestors\1940
  • Export Folder is .\Books\

The pathname with a leading backslash is relative notation and the absolute path depends on where you locate the Legacy folder. If the Legacy folder is located in C:\Documents\ for example, then the absolute pathname of the start folder would become C:\Documents\Legacy\1800 to 1970 A -- Block Family Ancestors\1800.

If you run the SynchPhotos command from a command line console with no parameters, you will see the following:

  • C:\Users\wtblo\LocalDocs\Legacy>SynchPhotos
  • Usage:
    • SynchPhotos source_path destination_path
  • Example:
    • SynchPhotos . F:\Photographs
  • C:\Users\wtblo\LocalDocs\Legacy>

In the example line, the period means use the current folder as the source (Legacy in this case) and the F:\Photograph might represent an external SSD and the contents of Legacy will be copied to Photographs. This is more than just a copy of all files; it is a mirror of your files.

Examples:

  • If you correct a spelling error in an image's comment metadata and then generate a new labeled image, SynchPhotos will only update the new/modified labeled image.
  • If you delete a labeled image, SynchPhotos will delete the same labeled image in the destination folder.
  • If you add a new folder or file, SynchPhotos will add a new folder or file to the destination folder.

PhotoExplorer

This is a desktop application for creating albums, entering metadata, and generating labeled copies of the images in a subfolder called \Labeled.

It is launched by double clicking on the PhotoExplorer.cmd file, or selecting PhotoExplorer.cmd, right clicking and selecting Open from the context menu. If you use a command prompt window, change the directory to the Legacy folder, type in the name PhotoExplorer and press the enter key.

PhotoPrinter

This is a desktop application for generating books from the labeled images. In can export in multiple ways:

  • Print the book to a printer.
  • Export the book as separate images to a book folder.
  • Export the book to a PDF.

Books can be simple chronological books specified by the start and end folders. If a query is defined, then the only photographs in the book will be those that are positive to the query. A query string like Barry Wayne Block will only include images where Barry AND Wayne AND Block are all in the comment metadata field. More than one query string can be in the query string by separating them with pipe symbols |:

  • Barry Wayne Block | Bobby Glenn 'Bob' Block

The above query says the comment must include Barry AND Wayne AND Block OR Bobby AND Glenn AND 'Bob' AND Block.

BuildPhotoIndex

The ability to query gigabytes of images depends on having an efficient indexing system. BuildPhotoIndex is a command line utility to build or incrementally update the index. Building an index from scratch can take a long time depending on how many images you have. In my case, it takes about 5 minutes to create a new index on my 30,000 labeled photographs. PhotoPrinter and QueryPhotoIndex will also build/update the index, so the BuildPhotoIndex is not entirely necessary unless you are not doing anything else.

QueryPhotoIndex

This is a command line application that can be used for debugging the index. When executed without any command line parameters, the following is displayed:

C:\Users\wtblo\LocalDocs\Legacy>QueryPhotoIndex
.
QueryPhotoIndex, Copyright (c) 2026, by W. T. Block.
.
A Windows command line program to read a photo index
  file called "PhotoIndex.phix" located by default in
  the working folder.
.
The index relates to the subfolders containing
  labeled photographs (.JPG) in subfolders called "Labeled".
.
The output represents a list of photograph pathnames
  that have comment metadata that matches the query
  parameters.
.
.
Usage:
.
.  QueryPhotoIndex query [index_folder]
.
Where:
.
.
Query format:
.
.  name or names separated with vertical bars: |.
.  word or words separated with vertical bars: |.
.
Examples:
.  "Maria Elisabeth Block 'Mary Beth' Cruise"
.    will look for a specific person's name.
.  "Barry Wayne Block|Bobby Glenn 'Bob' Block"
.    will look for either or both people's names.
.  "Houston Zoo"
.    will look for references to Houston Zoo.
.
Special case:
.  DUMP
.    will dump the contents of the index.
.  POST
.    will dump the contents of the index and the postings.
.

C:\Users\wtblo\LocalDocs\Legacy>

If the query contains more than one word, it must be enclosed in double quotes to make it look like a single parameter. The optional second parameter is the location of the index file, but since everything is based on working in the root folder, that should not be necessary.

Query Dump Example

C:\Users\wtblo\LocalDocs\Legacy>QueryPhotoIndex dump
No existing index found. Full rebuild.
00100 00200 ===== PHOTO INDEX DUMP =====
Image count: 244
Token count: 1478

-- Image Paths --
[0] .\1800 to 1970 A -- Block Family Ancestors\1800\1846.04.01 Bark Constitution\Labeled\1846_04_01_19_06_34.jpg
[1] .\1800 to 1970 A -- Block Family Ancestors\1800\1860 Hugh W. Hickok and Wife\Labeled\1860_01_01_19_12_49.jpg
[2] .\1800 to 1970 A -- Block Family Ancestors\1800\1860 Hugh W. Hickok and Wife\Labeled\1860_01_01_19_12_49_02.jpg
[3] .\1800 to 1970 A -- Block Family Ancestors\1800\1877.02.21 Frederick George Schmidt\Labeled\1877_02_21_19_17_44_03.jpg
...
[241] .\1800 to 1970 A -- Block Family Ancestors\1940\1949.04 Gilbert and Amelia First Vacation\Labeled\1949_04_01_13_57_47_02.jpg
[242] .\1800 to 1970 A -- Block Family Ancestors\1940\1949.04 Gilbert and Amelia First Vacation\Labeled\1949_04_01_13_57_48.jpg
[243] .\1800 to 1970 A -- Block Family Ancestors\1940\1949.04 Gilbert and Amelia First Vacation\Labeled\1949_04_01_13_57_48_02.jpg

-- Tokens --
04  (1 hits)
1  (3 hits)
1/2  (2 hits)
10  (8 hits)
100  (1 hits)
11  (4 hits)
11th  (1 hits)
12  (3 hits)
...
young  (1 hits)
younger  (5 hits)
youngest  (4 hits)
your  (1 hits)
yours  (1 hits)
===== END OF INDEX DUMP =====

Query Postings Example

This a more extensive version of the dump where the postings of the tokens are not just counted, but the actual postings are listed. It is an excellent illustration of how a reverse index is actually structured.

:\Users\wtblo\LocalDocs\Legacy>QueryPhotoIndex post
Incremental detection:
  New: 0
  Modified: 0
  Deleted: 0
===== PHOTO INDEX DUMP =====
Image count: 244
Token count: 1478

-- Image Paths --
[0] .\1800 to 1970 A -- Block Family Ancestors\1800\1846.04.01 Bark Constitution\Labeled\1846_04_01_19_06_34.jpg
[1] .\1800 to 1970 A -- Block Family Ancestors\1800\1860 Hugh W. Hickok and Wife\Labeled\1860_01_01_19_12_49.jpg
[2] .\1800 to 1970 A -- Block Family Ancestors\1800\1860 Hugh W. Hickok and Wife\Labeled\1860_01_01_19_12_49_02.jpg
[3] .\1800 to 1970 A -- Block Family Ancestors\1800\1877.02.21 Frederick George Schmidt\Labeled\1877_02_21_19_17_44_03.jpg
...
240] .\1800 to 1970 A -- Block Family Ancestors\1940\1949.04 Gilbert and Amelia First Vacation\Labeled\1949_04_01_13_57_47.jpg
[241] .\1800 to 1970 A -- Block Family Ancestors\1940\1949.04 Gilbert and Amelia First Vacation\Labeled\1949_04_01_13_57_47_02.jpg
[242] .\1800 to 1970 A -- Block Family Ancestors\1940\1949.04 Gilbert and Amelia First Vacation\Labeled\1949_04_01_13_57_48.jpg
[243] .\1800 to 1970 A -- Block Family Ancestors\1940\1949.04 Gilbert and Amelia First Vacation\Labeled\1949_04_01_13_57_48_02.jpg

-- Tokens --
04  (1 hits)
   IDs: 122
1  (3 hits)
   IDs: 0 17 182
1/2  (2 hits)
   IDs: 95 192
10  (8 hits)
   IDs: 18 60 65 76 107 115 121 208
100  (1 hits)
   IDs: 104
11  (4 hits)
   IDs: 119 137 147 148
...
you  (2 hits)
   IDs: 24 135
young  (1 hits)
   IDs: 82
younger  (5 hits)
   IDs: 42 46 58 59 80
youngest  (4 hits)
   IDs: 43 45 127 162
your  (1 hits)
   IDs: 135
yours  (1 hits)
   IDs: 230
===== END OF INDEX DUMP =====

As you can see, the number of hits for each token is listed, but also listed are the file IDs where the token was referenced.

Above, the token younger had 5 hits, but if the user discovered a comment where younger was misspelled yonger and corrected the error, running the post query again would remove the erroneous yonger token and another hit would be added to the younger token along with the file ID it was associated with. Since the order of the index is maintained, a file compare between the original post, and the new post would show exactly what changed.

Folder Structure Illustrated in Photo Explorer

  1. Working folder is called Photographs.
  2. The next level is the book folder: 1800 to 1970 A -- Block Family Ancestors.
  3. Under the book folder are year or decade folders depending on the number of photographs you have: 1900 in this image.
  4. The last level contains album folders: 1901 Will Block Rice Farm

Photo Explorer

Album folders contain the information at the top of the properties panel and are stored in a .album file in XML format:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Album>
	<Title value="1901 Will Block Rice Farm" type="string" />
	<Comment value="" type="string" />
	<Location value="Port Neches, TX, USA" type="string" />
	<Date value="1901:01:01 00:00:00" type="string" />
	<Artist value="" type="string" />
	<Copyright value="" type="string" />
	<Software value="" type="string" />
	<Keywords value="" type="string" />
</Album>

Depending which toolbar buttons are checked (orange in the screen shot represent checked items), album information can easily be copied into the selected image's metadata.

Here is a YouTube video demonstrating how to use PhotoExplorer:

2026.07.03 Photo Explorer Introduction

Example PhotoPrinter Document

The PhotoPrinter is designed to compile all your efforts in labeling and arranging photographs into books suitable for publication on Kindle. These books are formatted with letter-sized pages and margins that comply with Kindle's guidelines. Once the book's content is specified by completing the properties, a cover page is generated, a table of contents is created, pages are rendered, and the property panel displays a list of pages, enabling the user to easily navigate the entire document. The final step is to export the book as a PDF file, which can then be uploaded to Kindle.

Immediately after opening a document or creating a new document, the Built toolbar button is enabled. Pressing that button will render the pages of the book for the user to preview. The Table of Contents section of the Properties panel will navigate to the first page of the album when the user clicks on the album entry.

After building the book and verifying the output is what is expected, the user can export the book as a PDF or as a collection of page images in a folder under the Books folder with the same name as the title of the book. To generate a PDF, click on the PDF toolbar button. To generate image files for every page, press on the Export toolbar button. There is one other option for outputting the book and that is to print it. The printer can be a physical printer or a printer driver such as the Microsoft Print to PDF driver. This was the original intent, but the Microsoft driver fails on very large books. There are other PDF print drivers associated with other software that the user may find to be useful.

When exporting image files, this is the equivalent of scanning a book and getting images of each page. Most scanners have the ability to take those pages and assemble them as PDF files and again the user may find this approach useful.

The books follow Kindle rules with mirrored margins and are limited to letter size pages (8 1/2 x 11 inches).

Photo Printer

This example shows the structure of a .PP PhotoPrinter document and the fields used to generate a photo book.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PhotoPrinter>
	<Title value="Block Family Ancestors" type="string" />
	<Subtitle value="Photographs Collected by W. T. Block of Our Family" type="string" />
	<Publisher value="William T. Block III, Publisher" type="string" />
	<ISBN value="ISBN: 9798287035891" type="string" />
	<Copyright value="Copyright © 2025, by William Block, All rights reserved." type="string" />
	<Description value="My father, W. T. Block, Jr., dedicated countless hours to crafting photograph albums for each of his four children. He accomplished this task without the convenience of a computer, which meant he had to type labels for every single photograph and create duplicates by photographing them with a 35mm camera, then getting multiple prints developed. This book serves as my tribute to his efforts and ensures that my children can access all of his creations. By publishing it with an ISBN number, the information will be accessible to even more distant relatives, allowing his legacy to reach a wider audience." type="string" />
	<StartFolder value=".\1800 to 1970 A -- Block Family Ancestors\1800" type="string" />
	<EndFolder value=".\1800 to 1970 A -- Block Family Ancestors\1970 A" type="string" />
	<ExportFolder value=".\Books\" type="string" />
	<ExportPages value="" type="string" />
	<ExportDPI value="400" type="string" />
</PhotoPrinter>

The user does not see the underlying XML but fills in this information in a property panel illustrated on the left side of the screen shot above.

The three folder definitions: Start, End, Export Folders, use relative notation by beginning with a dot backslash. If the entire working folder (Photographs in these examples) are copied to another computer, cloud drive, or SSD, everything will continue to work in the new location.

The following YouTube video provides an introduction to using PhotoPrinter:

2026.07.04 Using the Photo Printer Application

Conclusion

This is just an introduction to the Photo Legacy applications and the linked YouTube videos will give more details on how to use the programs.