July 29, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Create a Chronological Photo Album with Java

  • September 21, 2006
  • By Vlad Kofman
  • Send Email »
  • More Articles »

Helper Objects

I will start with helper classes before moving on to the main algorithms. To filter out only specific file types to work with, I implemented classes using the standard java.io FileFilter interface, located in the filters package. The DirFilter filters out only directory file types and only those that I'm interested in.

Here is the code implementing the accept method from the java.io FileFilter interface.

public boolean accept(File file) {
      return file.isDirectory() && !excludeDir(file.getName());
   }

   private boolean excludeDir(String dirname) {
      for (int i = 0; i < exclude.length; i++) {
         if (exclude[i].equals(dirname)) {
            return true;
         }
      }

      return false;
   }

Similarly, the ImageFilesOnly filters out only image file types from the list of all files in a folder—in this case, only JPG files.

static String[] accepted = {"jpg", "JPG"};

   public boolean accept(File file) {
      if (file.isFile()) {
         String fn = file.getName();
         return (file.isFile() && (fn.endsWith(accepted[0]) ||
            fn.endsWith(accepted[1])));
      }
      return false;
   }

I apply the filters when I create the file objects representing a file system folders or files. For instance,

File dir = new File("C:\photos");
File[] pics = dir.listFiles(new ImageFilesOnly());

will create a list of JPG files located in the "photos" folder.

The ImageUtils from the util package contains APIs pertaining to the logical Image object, which represents one picture. I did not create a separate picture representation object in the beans package because all of the image properties required for the back-end engine are calculated in real time, and the image is represented simply by java.io.File. The APIs for the Image are:

  • getImageCameraManufacturer(File img)
  • getImageExifCameraModel(File img)
  • getImageExifCreationDate(File img)
  • getImageExifMetaData(File img, int meta)

As you may have guessed, all of these APIs use the metadata extractor library developed by Drew Noakes (see reference), and the names are self explanatory. One API of particular interest is the getImageExifCreationDate. It uses the FileTimes utility and has some logic in addition to the metadata extractor calls. Different manufacturers may call the field in the metadata of the file representing date the picture was taken differently, and in rare cases may not store that field at all. Therefore, I try different tags to locate the creation date of the picture. Otherwise, if image does not have this field, I get the time the file was created.

Here is the source code for this method. See the complete source for the other methods:

public static String getImageExifCreationDate(File img) {
   SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
   try {
      Metadata metadata = JpegMetadataReader.readMetadata(img);
      Directory exifDirectory =
         metadata.getDirectory(ExifDirectory.class);
      String dt = exifDirectory.getString(ExifDirectory.TAG_DATETIME);
      String dt_org =
         exifDirectory.getString(ExifDirectory.TAG_DATETIME_ORIGINAL);
      String dt_dt =
         exifDirectory.getString(ExifDirectory.TAG_DATETIME_DIGITIZED);

      if (dt_org != null && !dt_org.startsWith("0000")) {
         return dt_org;
      } else if (dt != null && !dt.startsWith("0000")) {
         return dt;
      } else if (dt_dt != null && !dt_dt.startsWith("0000")) {
         return dt_dt;
      } else {
         // not correct call . java has no API to get the file
         // create date of a file
         // return sdf.format(new Date(img.lastModified()));
         return sdf.format(new Date(FileTimes.getFileCreated(
            img.getPath())));
         }

      } catch (JpegProcessingException ex) {
         logger.error(ex, ex);
         return null;
      }
   }

The AlbumUtil class in the same util package that pertains to the Album object, which is a higher obstructed object than the single image and is represented by the folder on the file system. AlbumUtil is much more complex than the ImageUtil and has a lot of logic that constitutes a big part of the main back-end engine. For example, the getFolderDate method does a selective sampling of the file creation dates of the first, middle, and last picture in the folder using the getImageExifCreationDate method, which then returns the latest date. The getAlbumDate method uses the getFolderDate method to recursively calculate one master date for the whole Album, including subfolders and excluding folders designated by the EXCLUDE_DIR parameter.

Here is the source for the getAlbumDate method:

public static String getAlbumDate(File dir) {

   String[] dates = null;
   ArrayList aDates = new ArrayList();
   File[] innerAlbums =
      dir.listFiles(new DirFilter(new String[] {TNAILS_DIR}));
   if (innerAlbums != null && innerAlbums.length > 0) {
      String currentDirDate = getFolderDate(dir);
      if (currentDirDate != null) {    // if there are pictures in
                                       // the current dir
         aDates.add(currentDirDate);
      }
      for (int i = 0; i < innerAlbums.length; i++) {
         // recursive call to continue traversing the dir tree
         String date = getAlbumDate(innerAlbums[i]);
         if (date != null) {
            aDates.add(date);
         }
      }
      dates = (String[]) aDates.toArray(new String[aDates.size()]);
      Arrays.sort(dates, Collections.reverseOrder());
   }
   else {
      // there are no child dir - return date for this dir
      return getFolderDate(dir);
   }

   return dates[0];
}

For the complete source of the other methods, see the download section.

  • getAlbumDate(File dir)
  • getFolderDate(File dir)
  • outList(Object[] obj)
  • sortAlbums(Album[] albums)




Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel