diff --git a/wp-content/plugins/nextgen-gallery/changelog.txt b/wp-content/plugins/nextgen-gallery/changelog.txt
index 79c2691f243bcc3f9a39611711c5e97531f71804..e0f7ee9ca0d35807936e545c3357c5bf168f01ee 100644
--- a/wp-content/plugins/nextgen-gallery/changelog.txt
+++ b/wp-content/plugins/nextgen-gallery/changelog.txt
@@ -1,6 +1,10 @@
 NextGEN Gallery
 by Imagely
 
+= V2.2.14 - 09.18.2017 =
+* NEW:   EXIF and IPTC metadata are copied to new images when generating thumbnails, watermarks, or new sizes
+* Fixed: Metadata is read and preserved when "Resized images after upload" feature is enabled
+
 = V2.2.12 - 08.01.2017 =
 * Secured: Disabled Flash backend in plupload
 * Changed: Upgraded PHP-Parser version used when building plugin zips
diff --git a/wp-content/plugins/nextgen-gallery/nggallery.php b/wp-content/plugins/nextgen-gallery/nggallery.php
index a00878365fc52e9eadfa5a24f76fed854fb2de44..860855783aba153b9301244b5799e1daf69b131f 100644
--- a/wp-content/plugins/nextgen-gallery/nggallery.php
+++ b/wp-content/plugins/nextgen-gallery/nggallery.php
@@ -4,7 +4,7 @@ if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You
 /**
  * Plugin Name: NextGEN Gallery
  * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 18 million downloads.
- * Version: 2.2.12
+ * Version: 2.2.14
  * Author: Imagely
  * Plugin URI: https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/
  * Author URI: https://www.imagely.com
@@ -644,7 +644,7 @@ class C_NextGEN_Bootstrap
 		define('NGG_PRODUCT_URL', path_join(str_replace("\\", '/', NGG_PLUGIN_URL), 'products'));
 		define('NGG_MODULE_URL', path_join(str_replace("\\", '/', NGG_PRODUCT_URL), 'photocrati_nextgen/modules'));
 		define('NGG_PLUGIN_STARTED_AT', microtime());
-		define('NGG_PLUGIN_VERSION', '2.2.12');
+		define('NGG_PLUGIN_VERSION', '2.2.14');
 
 		if (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG)
 			define('NGG_SCRIPT_VERSION', (string)mt_rand(0, mt_getrandmax()));
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php
index 03cbc7f05facbf2cf1d87cf7e2c5e8bd2ef6c721..8c0f3f74b9811ffc3b56ffb22b64b6bfd651afb5 100644
--- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_album/package.module.nextgen_basic_album.php
@@ -884,11 +884,7 @@ class A_NextGen_Basic_Extended_Album_Form extends Mixin_NextGen_Basic_Album_Form
      */
     function enqueue_static_resources()
     {
-        wp_enqueue_script('nextgen_basic_extended_albums_settings_script', $this->object->get_static_url('photocrati-nextgen_basic_album#extended_settings.js'), array('jquery.nextgen_radio_toggle'), NGG_SCRIPT_VERSION);
-        $atp = C_Attach_Controller::get_instance();
-        if ($atp != null) {
-            $atp->mark_script('nextgen_basic_extended_albums_settings_script');
-        }
+        $this->object->enqueue_script('nextgen_basic_extended_albums_settings_script', $this->object->get_static_url('photocrati-nextgen_basic_album#extended_settings.js'), array('jquery.nextgen_radio_toggle'));
     }
 }
 /**
@@ -916,10 +912,6 @@ class A_NextGen_Basic_Compact_Album_Form extends Mixin_NextGen_Basic_Album_Form
      */
     function enqueue_static_resources()
     {
-        wp_enqueue_script('nextgen_basic_compact_albums_settings_script', $this->object->get_static_url('photocrati-nextgen_basic_album#compact_settings.js'), array('jquery.nextgen_radio_toggle'), NGG_SCRIPT_VERSION);
-        $atp = C_Attach_Controller::get_instance();
-        if ($atp != null) {
-            $atp->mark_script('nextgen_basic_compact_albums_settings_script');
-        }
+        $this->object->enqueue_script('nextgen_basic_compact_albums_settings_script', $this->object->get_static_url('photocrati-nextgen_basic_album#compact_settings.js'), array('jquery.nextgen_radio_toggle'));
     }
 }
\ No newline at end of file
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php
index 867e62565069a0560663c5d5c04fafa5e8e49a29..d133e8a0811a853f477b68b4052bc7edf1b3bc40 100644
--- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_gallery/package.module.nextgen_basic_gallery.php
@@ -295,11 +295,7 @@ class A_NextGen_Basic_Slideshow_Form extends Mixin_Display_Type_Form
     }
     function enqueue_static_resources()
     {
-        wp_enqueue_script('nextgen_basic_slideshow_settings-js', $this->get_static_url('photocrati-nextgen_basic_gallery#slideshow/nextgen_basic_slideshow_settings.js'), array('jquery.nextgen_radio_toggle'), NGG_SCRIPT_VERSION);
-        $atp = C_Attach_Controller::get_instance();
-        if ($atp != null) {
-            $atp->mark_script('nextgen_basic_slideshow_settings-js');
-        }
+        $this->object->enqueue_script('nextgen_basic_slideshow_settings-js', $this->get_static_url('photocrati-nextgen_basic_gallery#slideshow/nextgen_basic_slideshow_settings.js'), array('jquery.nextgen_radio_toggle'));
     }
     /**
      * Returns a list of fields to render on the settings page
@@ -357,12 +353,8 @@ class A_NextGen_Basic_Thumbnail_Form extends Mixin_Display_Type_Form
      */
     function enqueue_static_resources()
     {
-        wp_enqueue_style('nextgen_basic_thumbnails_settings', $this->object->get_static_url('photocrati-nextgen_basic_gallery#thumbnails/nextgen_basic_thumbnails_settings.css'), FALSE, NGG_SCRIPT_VERSION);
-        wp_enqueue_script('nextgen_basic_thumbnails_settings', $this->object->get_static_url('photocrati-nextgen_basic_gallery#thumbnails/nextgen_basic_thumbnails_settings.js'), array('jquery.nextgen_radio_toggle'), NGG_SCRIPT_VERSION);
-        $atp = C_Attach_Controller::get_instance();
-        if ($atp != null) {
-            $atp->mark_script('nextgen_basic_thumbnails_settings');
-        }
+        $this->object->enqueue_style('nextgen_basic_thumbnails_settings', $this->object->get_static_url('photocrati-nextgen_basic_gallery#thumbnails/nextgen_basic_thumbnails_settings.css'));
+        $this->object->enqueue_script('nextgen_basic_thumbnails_settings', $this->object->get_static_url('photocrati-nextgen_basic_gallery#thumbnails/nextgen_basic_thumbnails_settings.js'), array('jquery.nextgen_radio_toggle'));
     }
     /**
      * Returns a list of fields to render on the settings page
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_tagcloud/package.module.nextgen_basic_tagcloud.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_tagcloud/package.module.nextgen_basic_tagcloud.php
index b65a2acefc148d5b5ed200c3c1523aa684ad4788..2274d48a156b7daee8d1a0a5b7e3d80cd678d778 100644
--- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_tagcloud/package.module.nextgen_basic_tagcloud.php
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_tagcloud/package.module.nextgen_basic_tagcloud.php
@@ -89,12 +89,7 @@ class A_NextGen_Basic_Tagcloud_Form extends Mixin_Display_Type_Form
     }
     function enqueue_static_resources()
     {
-        $path = 'photocrati-nextgen_basic_tagcloud#settings.css';
-        wp_enqueue_style('nextgen_basic_tagcloud_settings-css', $this->get_static_url($path), FALSE, NGG_SCRIPT_VERSION);
-        $atp = C_Attach_Controller::get_instance();
-        if (!is_null($atp)) {
-            $atp->mark_script($path);
-        }
+        $this->object->enqueue_style('nextgen_basic_tagcloud_settings-css', $this->get_static_url('photocrati-nextgen_basic_tagcloud#settings.css'));
     }
     function _render_nextgen_basic_tagcloud_number_field($display_type)
     {
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php
index 3681a40fbaaf653cfda6f953c6894b66690d2e90..8253aa89fc6d143170dd5b7f3f3ce94ae150942a 100644
--- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_basic_templates/package.module.nextgen_basic_templates.php
@@ -168,13 +168,9 @@ class A_NextGen_Basic_Template_Form extends Mixin
     }
     function enqueue_static_resources()
     {
-        wp_enqueue_style('ngg_template_settings', $this->get_static_url('photocrati-nextgen_basic_templates#ngg_template_settings.css'), FALSE, NGG_SCRIPT_VERSION);
-        wp_enqueue_script('ngg_template_settings', $this->get_static_url('photocrati-nextgen_basic_templates#ngg_template_settings.js'), array('ngg_select2'), NGG_SCRIPT_VERSION, TRUE);
+        wp_enqueue_style('ngg_template_settings', $this->get_static_url('photocrati-nextgen_basic_templates#ngg_template_settings.css'));
+        wp_enqueue_script('ngg_template_settings', $this->get_static_url('photocrati-nextgen_basic_templates#ngg_template_settings.js'), array('ngg_select2'), TRUE);
         wp_localize_script('ngg_template_settings', 'ngg_template_settings', array('placeholder_text' => __('No template selected')));
-        $atp = C_Attach_Controller::get_instance();
-        if ($atp != null) {
-            $atp->mark_script('ngg_template_settings');
-        }
     }
 }
 /**
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php
index b2ec5fdf788ed2422edcad12f974fbb2e57e0a58..759e4db8c8dbc14fef0b65bb1345002975cec6d4 100644
--- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/module.nextgen_data.php
@@ -50,6 +50,7 @@ class M_NextGen_Data extends C_Base_Module
     function get_type_list()
     {
         return array(
+            'C_Exif_Writer_Wrapper' => 'class.exif_writer_wrapper.php',
             'A_Attachment_Datamapper' => 'adapter.attachment_datamapper.php',
             'A_Customtable_Sorting_Datamapper' => 'adapter.customtable_sorting_datamapper.php',
             'A_Nextgen_Data_Factory' => 'adapter.nextgen_data_factory.php',
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php
index 7da82ca64fb5ef02a3b239d1bcd27023e992c4e6..b5e8b8a0d609e4b752d6d1402875a3dd03d02383 100644
--- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php
@@ -235,6 +235,19 @@ class Mixin_Album_Mapper extends Mixin
         }
     }
 }
+class C_Exif_Writer_Wrapper
+{
+    // Because our C_Exif_Writer class relies on PEL (a library which uses namespaces) we wrap
+    // its use through this method which performs a PHP version check before loading the class file
+    public static function copy_metadata($old_file, $new_file)
+    {
+        if (version_compare(phpversion(), '5.3.0', '<')) {
+            return;
+        }
+        require_once __DIR__ . DIRECTORY_SEPARATOR . 'pel-0.9.6' . DIRECTORY_SEPARATOR . 'class.exif_writer.php';
+        C_Exif_Writer::copy_metadata($old_file, $new_file);
+    }
+}
 class Mixin_NextGen_Gallery_Validation
 {
     /**
@@ -1206,46 +1219,51 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin
             if (!is_writable($upload_dir)) {
                 throw new E_InsufficientWriteAccessException(FALSE, $upload_dir, FALSE);
             }
-            // Save the image
-            if ($image_id = $this->object->_image_mapper->save($image)) {
-                try {
-                    // Try writing the image
-                    $fp = fopen($abs_filename, 'wb');
-                    fwrite($fp, $this->maybe_base64_decode($data));
-                    fclose($fp);
-                    if ($settings->imgBackup) {
-                        $this->object->backup_image($image);
-                    }
-                    if ($settings->imgAutoResize) {
-                        $this->object->generate_image_clone($abs_filename, $abs_filename, $this->object->get_image_size_params($image_id, 'full'));
-                    }
-                    // Ensure that fullsize dimensions are added to metadata array
-                    $dimensions = getimagesize($abs_filename);
-                    $full_meta = array('width' => $dimensions[0], 'height' => $dimensions[1], 'md5' => $this->object->get_image_checksum($image, 'full'));
-                    if (!isset($image->meta_data) or is_string($image->meta_data) && strlen($image->meta_data) == 0) {
-                        $image->meta_data = array();
-                    }
-                    $image->meta_data = array_merge($image->meta_data, $full_meta);
-                    $image->meta_data['full'] = $full_meta;
-                    // Generate a thumbnail for the image
-                    $this->object->generate_thumbnail($image);
-                    // Set gallery preview image if missing
-                    C_Gallery_Mapper::get_instance()->set_preview_image($gallery, $image_id, TRUE);
-                    // Notify other plugins that an image has been added
-                    do_action('ngg_added_new_image', $image);
-                    // delete dirsize after adding new images
-                    delete_transient('dirsize_cache');
-                    // Seems redundant to above hook. Maintaining for legacy purposes
-                    do_action('ngg_after_new_images_added', $gallery_id, array($image->{$image_key}));
-                } catch (E_No_Image_Library_Exception $ex) {
-                    throw $ex;
-                } catch (E_Clean_Exit $ex) {
-                    // pass
-                } catch (Exception $ex) {
-                    throw new E_InsufficientWriteAccessException(FALSE, $abs_filename, FALSE, $ex);
+            try {
+                // Try writing the image
+                $fp = fopen($abs_filename, 'wb');
+                fwrite($fp, $this->maybe_base64_decode($data));
+                fclose($fp);
+                // Save the image
+                $image_id = $this->object->_image_mapper->save($image);
+                if (!$image_id) {
+                    throw new E_InvalidEntityException();
                 }
-            } else {
-                throw new E_InvalidEntityException();
+                if ($settings->imgBackup) {
+                    $this->object->backup_image($image);
+                }
+                if ($settings->imgAutoResize) {
+                    $this->object->generate_image_clone($abs_filename, $abs_filename, $this->object->get_image_size_params($image_id, 'full'));
+                }
+                $this->object->_image_mapper->_use_cache = FALSE;
+                $image = $this->object->_image_mapper->find($image_id);
+                $this->object->_image_mapper->_use_cache = TRUE;
+                // Ensure that fullsize dimensions are added to metadata array
+                $dimensions = getimagesize($abs_filename);
+                $full_meta = array('width' => $dimensions[0], 'height' => $dimensions[1], 'md5' => $this->object->get_image_checksum($image, 'full'));
+                if (!isset($image->meta_data) or is_string($image->meta_data) && strlen($image->meta_data) == 0) {
+                    $image->meta_data = array();
+                }
+                $image->meta_data = array_merge($image->meta_data, $full_meta);
+                $image->meta_data['full'] = $full_meta;
+                // Don't forget to append the 'full' entry in meta_data in the db
+                $this->object->_image_mapper->save($image);
+                // Generate a thumbnail for the image
+                $this->object->generate_thumbnail($image);
+                // Set gallery preview image if missing
+                C_Gallery_Mapper::get_instance()->set_preview_image($gallery, $image_id, TRUE);
+                // Notify other plugins that an image has been added
+                do_action('ngg_added_new_image', $image);
+                // delete dirsize after adding new images
+                delete_transient('dirsize_cache');
+                // Seems redundant to above hook. Maintaining for legacy purposes
+                do_action('ngg_after_new_images_added', $gallery_id, array($image->{$image_key}));
+            } catch (E_No_Image_Library_Exception $ex) {
+                throw $ex;
+            } catch (E_Clean_Exit $ex) {
+                // pass
+            } catch (Exception $ex) {
+                throw new E_InsufficientWriteAccessException(FALSE, $abs_filename, FALSE, $ex);
             }
         } else {
             throw new E_EntityNotFoundException();
@@ -1643,6 +1661,7 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin
      * @param string $image_path
      * @param string $clone_path
      * @param array $params
+     * @param bool $save Whether to call the image save() method
      * @return object
      */
     function generate_image_clone($image_path, $clone_path, $params)
@@ -1777,13 +1796,7 @@ class Mixin_GalleryStorage_Driver_Base extends Mixin
                 }
                 $thumbnail = apply_filters('ngg_before_save_thumbnail', $thumbnail);
                 $thumbnail->save($destpath, $quality);
-                // IF the original contained IPTC metadata we should attempt to copy it
-                if (isset($detailed_size['APP13']) && function_exists('iptcembed')) {
-                    $metadata = @iptcembed($detailed_size['APP13'], $destpath);
-                    $fp = @fopen($destpath, 'wb');
-                    @fwrite($fp, $metadata);
-                    @fclose($fp);
-                }
+                C_Exif_Writer_Wrapper::copy_metadata($image_path, $destpath);
             }
         }
         return $thumbnail;
@@ -1958,7 +1971,7 @@ class Mixin_Gallery_Image_Mapper extends Mixin
     function _save_entity($entity)
     {
         $entity->updated_at = time();
-        // If successfully saved, then import metadata and
+        // If successfully saved then import metadata
         $retval = $this->call_parent('_save_entity', $entity);
         if ($retval) {
             include_once NGGALLERY_ABSPATH . '/admin/functions.php';
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/AUTHORS b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..1b3b349c3f24587e8285adb14968c39311817d02
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/AUTHORS
@@ -0,0 +1,53 @@
+AUTHORS file for PEL: PHP Exif Library.  A library with support for
+reading and writing Exif headers in JPEG and TIFF images using PHP.
+
+Copyright (C) 2004, 2005, 2006, 2007  Martin Geisler.
+Copyright (c) 2008, 2009 Lars Olesen
+Copyright (c) 2015 Johannes Weberhofer
+Licensed under the GNU GPL, see COPYING for details.
+
+
+Credits
+*******
+
+PEL is written by Martin Geisler <mgeisler@users.sourceforge.net> and
+is now maintained by Lars Olesen <lars@intraface.dk>
+and <jweberhofer@weberhofer.at>
+
+The source started out as a port of the nice, clean C code found in
+libexif.  Most of the translations included with PEL also originates
+from the libexif project, see below for details.
+
+
+Test Image Contributors
+***********************
+
+Bernhard Bittel: Nikon E950 and E5000 test images.
+
+Stéphanie Bittel: Canon IXUS II test image.
+
+Lars Geisler: Nikon Coolscan IV ED test image.
+
+Mikkel Krøigård: Canon PowerShot S60 test image.
+
+Paul Mitchum: Pentax *ist DS and Olympus C-5050z test images.
+
+Lisbeth Nygaard Pedersen: Leica D-LUX test image.
+
+Thomas B. Pedersen: Olympus C-50z and C-765z test images.
+
+
+Translators
+***********
+
+Danish: Martin Geisler.
+
+French: Arnaud Launay (for libexif) and David Lesieur.
+
+German: Hans Ulrich Niedermann, Lutz Möller (for libexif).
+
+Japanese: Tadashi Jokagi.
+
+Polish: Jakub Bogusz (for libexif).
+
+Spanish: Fabian Mandelbaum (for libexif).
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/COPYING b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..3912109b5cd65a68039d473c11c9f7ac2303e06d
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/autoload.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/autoload.php
new file mode 100644
index 0000000000000000000000000000000000000000..f86d0adbb173103de349de8dfa1688e75dac9bcb
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/autoload.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2015, Johannes Weberhofer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+/**
+ * Register autoloader for pel
+ */
+spl_autoload_register(function ($class) {
+    if (substr_compare($class, 'lsolesen\\pel\\', 0, 13) === 0) {
+        $classname = str_replace('lsolesen\\pel\\', '', $class);
+        $load = realpath(__DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . $classname . '.php');
+        if ($load !== false) {
+            include_once realpath($load);
+        }
+    }
+});
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/class.exif_writer.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/class.exif_writer.php
new file mode 100644
index 0000000000000000000000000000000000000000..e249d606dfe75686a60f33011dc4c58b3b25a033
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/class.exif_writer.php
@@ -0,0 +1,106 @@
+<?php
+
+// This file resides in the PEL directory so that it is not processed during the NextGen
+// build process as the NGG package files cannot contain PHP 5.3+ code yet. See the
+// C_Exif_Writer_Wrapper class which loads this file outside of the POPE module system.
+
+require_once('autoload.php');
+
+use lsolesen\pel\PelDataWindow;
+use lsolesen\pel\PelJpeg;
+use lsolesen\pel\PelTiff;
+use lsolesen\pel\PelExif;
+use lsolesen\pel\PelIfd;
+
+class C_Exif_Writer
+{
+    static public function copy_metadata($old_file, $new_file)
+    {
+        $data = new PelDataWindow(@file_get_contents($old_file));
+        $exif = new PelExif();
+
+        if (PelJpeg::isValid($data))
+        {
+            $jpeg = $file = new PelJpeg();
+            $jpeg->load($data);
+            $exif = $jpeg->getExif();
+
+            if ($exif === NULL)
+            {
+                $exif = new PelExif();
+                $jpeg->setExif($exif);
+
+                $tiff = new PelTiff();
+                $exif->setTiff($tiff);
+            }
+            else {
+                $tiff = $exif->getTiff();
+            }
+
+        }
+        elseif (PelTiff::isValid($data)) {
+            $tiff = $file = new PellTiff();
+            $tiff->load($data);
+        }
+        else {
+            return;
+        }
+
+        $ifd0 = $tiff->getIfd();
+        if ($ifd0 === NULL)
+        {
+            $ifd0 = new PelIfd(PelIfd::IFD0);
+            $tiff->setIfd($ifd0);
+        }
+
+        // Copy EXIF data to the new image and write it
+        $new_image = new PelJpeg($new_file);
+        $tiff->setIfd($ifd0);
+        $exif->setTiff($tiff);
+        $new_image->setExif($exif);
+        $new_image->saveFile($new_file);
+
+        // IF the original contained IPTC metadata we should copy it
+        getimagesize($old_file, $iptc);
+        if (isset($iptc['APP13']) && function_exists('iptcembed'))
+        {
+            $parsed = iptcparse($iptc['APP13']);
+            $newiptc = '';
+            foreach ($parsed as $key => $value) {
+                $tag = str_replace("2#", '', $key);
+                $newiptc .= self::build_iptc_tag($tag, $value[0]);
+            }
+
+            $metadata = iptcembed($newiptc, $new_file);
+            $fp = fopen($new_file, 'wb');
+            fwrite($fp, $metadata);
+            fclose($fp);
+        }
+    }
+
+    public static function build_iptc_tag($tag, $value)
+    {
+        $length = strlen($value);
+        if ($length >= 0x8000)
+        {
+            return chr(0x1c)
+                   . chr(2)
+                   . chr($tag)
+                   . chr(0x80)
+                   . chr(0x04)
+                   . chr(($length >> 24) & 0xff)
+                   . chr(($length >> 16) & 0xff)
+                   . chr(($length >> 8 ) & 0xff)
+                   . chr(($length ) & 0xff)
+                   . $value;
+        }
+        else {
+            return chr(0x1c)
+                   . chr(2)
+                   . chr($tag)
+                   . chr($length >> 8)
+                   . chr($length & 0xff)
+                   . $value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/Pel.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/Pel.php
new file mode 100644
index 0000000000000000000000000000000000000000..6de2489e3a020d83a4d5e9f8d3d5abc76b2fd72c
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/Pel.php
@@ -0,0 +1,365 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Class with miscellaneous static methods.
+ *
+ * This class will contain various methods that govern the overall
+ * behavior of PEL.
+ *
+ * Debugging output from PEL can be turned on and off by assigning
+ * true or false to {@link Pel::$debug}.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class Pel
+{
+
+    /**
+     * Flag that controls if dgettext can be used.
+     * Is set to true or fals at the first access
+     *
+     * @var boolean|NULL
+     */
+    private static $hasdgetext = null;
+
+    /**
+     * Flag for controlling debug information.
+     *
+     * The methods producing debug information ({@link debug()} and
+     * {@link warning()}) will only output something if this variable is
+     * set to true.
+     *
+     * @var boolean
+     */
+    private static $debug = false;
+
+    /**
+     * Flag for strictness of parsing.
+     *
+     * If this variable is set to true, then most errors while loading
+     * images will result in exceptions being thrown. Otherwise a
+     * warning will be emitted (using {@link Pel::warning}) and the
+     * exceptions will be appended to {@link Pel::$exceptions}.
+     *
+     * Some errors will still be fatal and result in thrown exceptions,
+     * but an effort will be made to skip over as much garbage as
+     * possible.
+     *
+     * @var boolean
+     */
+    private static $strict = false;
+
+    /**
+     * Stored exceptions.
+     *
+     * When {@link Pel::$strict} is set to false exceptions will be
+     * accumulated here instead of being thrown.
+     */
+    private static $exceptions = array();
+
+    /**
+     * Quality setting for encoding JPEG images.
+     *
+     * This controls the quality used then PHP image resources are
+     * encoded into JPEG images. This happens when you create a
+     * {@link PelJpeg} object based on an image resource.
+     *
+     * The default is 75 for average quality images, but you can change
+     * this to an integer between 0 and 100.
+     *
+     * @var int
+     */
+    private static $quality = 75;
+
+    /**
+     * Set the JPEG encoding quality.
+     *
+     * @param int $quality
+     *            an integer between 0 and 100 with 75 being
+     *            average quality and 95 very good quality.
+     */
+    public static function setJPEGQuality($quality)
+    {
+        self::$quality = $quality;
+    }
+
+    /**
+     * Get current setting for JPEG encoding quality.
+     *
+     * @return int the quality.
+     */
+    public static function getJPEGQuality()
+    {
+        return self::$quality;
+    }
+
+    /**
+     * Return list of stored exceptions.
+     *
+     * When PEL is parsing in non-strict mode, it will store most
+     * exceptions instead of throwing them. Use this method to get hold
+     * of them when a call returns.
+     *
+     * Code for using this could look like this:
+     *
+     * <code>
+     * Pel::setStrictParsing(true);
+     * Pel::clearExceptions();
+     *
+     * $jpeg = new PelJpeg($file);
+     *
+     * // Check for exceptions.
+     * foreach (Pel::getExceptions() as $e) {
+     * printf("Exception: %s\n", $e->getMessage());
+     * if ($e instanceof PelEntryException) {
+     * // Warn about entries that couldn't be loaded.
+     * printf("Warning: Problem with %s.\n",
+     * PelTag::getName($e->getType(), $e->getTag()));
+     * }
+     * }
+     * </code>
+     *
+     * This gives applications total control over the amount of error
+     * messages shown and (hopefully) provides the necessary information
+     * for proper error recovery.
+     *
+     * @return array the exceptions.
+     */
+    public static function getExceptions()
+    {
+        return self::$exceptions;
+    }
+
+    /**
+     * Clear list of stored exceptions.
+     *
+     * Use this function before a call to some method if you intend to
+     * check for exceptions afterwards.
+     */
+    public static function clearExceptions()
+    {
+        self::$exceptions = array();
+    }
+
+    /**
+     * Conditionally throw an exception.
+     *
+     * This method will throw the passed exception when strict parsing
+     * in effect (see {@link setStrictParsing()}). Otherwise the
+     * exception is stored (it can be accessed with {@link
+     * getExceptions()}) and a warning is issued (with {@link
+     * Pel::warning}).
+     *
+     * @param PelException $e
+     *            the exceptions.
+     */
+    public static function maybeThrow(PelException $e)
+    {
+        if (self::$strict) {
+            throw $e;
+        } else {
+            self::$exceptions[] = $e;
+            self::warning('%s (%s:%s)', $e->getMessage(), basename($e->getFile()), $e->getLine());
+        }
+    }
+
+    /**
+     * Enable/disable strict parsing.
+     *
+     * If strict parsing is enabled, then most errors while loading
+     * images will result in exceptions being thrown. Otherwise a
+     * warning will be emitted (using {@link Pel::warning}) and the
+     * exceptions will be stored for later use via {@link
+     * getExceptions()}.
+     *
+     * Some errors will still be fatal and result in thrown exceptions,
+     * but an effort will be made to skip over as much garbage as
+     * possible.
+     *
+     * @param boolean $flag
+     *            use true to enable strict parsing, false to
+     *            diable.
+     */
+    public static function setStrictParsing($flag)
+    {
+        self::$strict = $flag;
+    }
+
+    /**
+     * Get current setting for strict parsing.
+     *
+     * @return boolean true if strict parsing is in effect, false
+     *         otherwise.
+     */
+    public static function getStrictParsing()
+    {
+        return self::$strict;
+    }
+
+    /**
+     * Enable/disable debugging output.
+     *
+     * @param boolean $flag
+     *            use true to enable debug output, false to
+     *            diable.
+     */
+    public static function setDebug($flag)
+    {
+        self::$debug = $flag;
+    }
+
+    /**
+     * Get current setting for debug output.
+     *
+     * @return boolean true if debug is enabled, false otherwise.
+     */
+    public static function getDebug()
+    {
+        return self::$debug;
+    }
+
+    /**
+     * Conditionally output debug information.
+     *
+     * This method works just like printf() except that it always
+     * terminates the output with a newline, and that it only outputs
+     * something if the {@link Pel::$debug} is true.
+     *
+     * @param string $format
+     *            the format string.
+     *
+     * @param mixed ...$args
+     *            any number of arguments can be given. The
+     *            arguments will be available for the format string as usual with
+     *            sprintf().
+     */
+    public static function debug($format)
+    {
+        if (self::$debug) {
+            $args = func_get_args();
+            $str = array_shift($args);
+            vprintf($str . "\n", $args);
+        }
+    }
+
+    /**
+     * Conditionally output a warning.
+     *
+     * This method works just like printf() except that it prepends the
+     * output with the string 'Warning: ', terminates the output with a
+     * newline, and that it only outputs something if the PEL_DEBUG
+     * defined to some true value.
+     *
+     * @param string $format
+     *            the format string.
+     *
+     * @param mixed ...$args
+     *            any number of arguments can be given. The
+     *            arguments will be available for the format string as usual with
+     *            sprintf().
+     */
+    public static function warning($format)
+    {
+        if (self::$debug) {
+            $args = func_get_args();
+            $str = array_shift($args);
+            vprintf('Warning: ' . $str . "\n", $args);
+        }
+    }
+
+    /**
+     * Translate a string.
+     *
+     * This static function will use Gettext to translate a string. By
+     * always using this function for static string one is assured that
+     * the translation will be taken from the correct text domain.
+     * Dynamic strings should be passed to {@link fmt} instead.
+     *
+     * @param string $str
+     *            the string that should be translated.
+     *
+     * @return string the translated string, or the original string if
+     *         no translation could be found.
+     */
+    public static function tra($str)
+    {
+        return self::dgettextWrapper('pel', $str);
+    }
+
+    /**
+     * Translate and format a string.
+     *
+     * This static function will first use Gettext to translate a format
+     * string, which will then have access to any extra arguments. By
+     * always using this function for dynamic string one is assured that
+     * the translation will be taken from the correct text domain. If
+     * the string is static, use {@link tra} instead as it will be
+     * faster.
+     *
+     * @param string $format
+     *            the format string. This will be translated
+     *            before being used as a format string.
+     *
+     * @param mixed ...$args
+     *            any number of arguments can be given. The
+     *            arguments will be available for the format string as usual with
+     *            sprintf().
+     *
+     * @return string the translated string, or the original string if
+     *         no translation could be found.
+     */
+    public static function fmt($format)
+    {
+        $args = func_get_args();
+        $str = array_shift($args);
+        return vsprintf(self::dgettextWrapper('pel', $str), $args);
+    }
+
+    /**
+     * Warapper for dgettext.
+     * The untranslated stub will be return in the case that dgettext is not available.
+     *
+     * @param string $domain
+     * @param string $str
+     * @return string
+     */
+    private static function dgettextWrapper($domain, $str)
+    {
+        if (self::$hasdgetext === null) {
+            self::$hasdgetext = function_exists('dgettext');
+            if (self::$hasdgetext === true) {
+                bindtextdomain('pel', __DIR__ . '/locale');
+            }
+        }
+        if (self::$hasdgetext) {
+            return dgettext($domain, $str);
+        } else {
+            return $str;
+        }
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelConvert.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelConvert.php
new file mode 100644
index 0000000000000000000000000000000000000000..474c48a61273c69e3701cbe1f8536e2f0cc9c3a5
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelConvert.php
@@ -0,0 +1,418 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Routines for converting back and forth between bytes and integers.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Conversion functions to and from bytes and integers.
+ *
+ * The functions found in this class are used to convert bytes into
+ * integers of several sizes ({@link bytesToShort}, {@link
+ * bytesToLong}, and {@link bytesToRational}) and convert integers of
+ * several sizes into bytes ({@link shortToBytes} and {@link
+ * longToBytes}).
+ *
+ * All the methods are static and they all rely on an argument that
+ * specifies the byte order to be used, this must be one of the class
+ * constants {@link LITTLE_ENDIAN} or {@link BIG_ENDIAN}. These
+ * constants will be referred to as the pseudo type PelByteOrder
+ * throughout the documentation.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelConvert
+{
+
+    /**
+     * Little-endian (Intel) byte order.
+     *
+     * Data stored in little-endian byte order store the least
+     * significant byte first, so the number 0x12345678 becomes 0x78
+     * 0x56 0x34 0x12 when stored with little-endian byte order.
+     */
+    const LITTLE_ENDIAN = true;
+
+    /**
+     * Big-endian (Motorola) byte order.
+     *
+     * Data stored in big-endian byte order store the most significant
+     * byte first, so the number 0x12345678 becomes 0x12 0x34 0x56 0x78
+     * when stored with big-endian byte order.
+     */
+    const BIG_ENDIAN = false;
+
+    /**
+     * Convert an unsigned short into two bytes.
+     *
+     * @param integer $value
+     *            the unsigned short that will be converted. The lower
+     *            two bytes will be extracted regardless of the actual size passed.
+     *
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     *
+     * @return string the bytes representing the unsigned short.
+     */
+    public static function shortToBytes($value, $endian)
+    {
+        if ($endian == self::LITTLE_ENDIAN) {
+            return chr($value) . chr($value >> 8);
+        } else {
+            return chr($value >> 8) . chr($value);
+        }
+    }
+
+    /**
+     * Convert a signed short into two bytes.
+     *
+     * @param integer $value
+     *            the signed short that will be converted. The lower
+     *            two bytes will be extracted regardless of the actual size passed.
+     *
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     *
+     * @return string the bytes representing the signed short.
+     */
+    public static function sShortToBytes($value, $endian)
+    {
+        /*
+         * We can just use shortToBytes, since signed shorts fits well
+         * within the 32 bit signed integers used in PHP.
+         */
+        return self::shortToBytes($value, $endian);
+    }
+
+    /**
+     * Convert an unsigned long into four bytes.
+     *
+     * Because PHP limits the size of integers to 32 bit signed, one
+     * cannot really have an unsigned integer in PHP. But integers
+     * larger than 2^31-1 will be promoted to 64 bit signed floating
+     * point numbers, and so such large numbers can be handled too.
+     *
+     * @param integer $value
+     *            the unsigned long that will be converted. The
+     *            argument will be treated as an unsigned 32 bit integer and the
+     *            lower four bytes will be extracted. Treating the argument as an
+     *            unsigned integer means that the absolute value will be used. Use
+     *            {@link sLongToBytes} to convert signed integers.
+     *
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     *
+     * @return string the bytes representing the unsigned long.
+     */
+    public static function longToBytes($value, $endian)
+    {
+        /*
+         * We cannot convert the number to bytes in the normal way (using
+         * shifts and modulo calculations) because the PHP operator >> and
+         * function chr() clip their arguments to 2^31-1, which is the
+         * largest signed integer known to PHP. But luckily base_convert
+         * handles such big numbers.
+         */
+        $hex = str_pad(base_convert($value, 10, 16), 8, '0', STR_PAD_LEFT);
+        if ($endian == self::LITTLE_ENDIAN) {
+            return (chr(hexdec($hex{6} . $hex{7})) . chr(hexdec($hex{4} . $hex{5})) . chr(hexdec($hex{2} . $hex{3})) .
+                 chr(hexdec($hex{0} . $hex{1})));
+        } else {
+            return (chr(hexdec($hex{0} . $hex{1})) . chr(hexdec($hex{2} . $hex{3})) . chr(hexdec($hex{4} . $hex{5})) .
+                 chr(hexdec($hex{6} . $hex{7})));
+        }
+    }
+
+    /**
+     * Convert a signed long into four bytes.
+     *
+     * @param integer $value
+     *            the signed long that will be converted. The argument
+     *            will be treated as a signed 32 bit integer, from which the lower
+     *            four bytes will be extracted.
+     *
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     *
+     * @return string the bytes representing the signed long.
+     */
+    public static function sLongToBytes($value, $endian)
+    {
+        /*
+         * We can convert the number into bytes in the normal way using
+         * shifts and modulo calculations here (in contrast with
+         * longToBytes) because PHP automatically handles 32 bit signed
+         * integers for us.
+         */
+        if ($endian == self::LITTLE_ENDIAN) {
+            return (chr($value) . chr($value >> 8) . chr($value >> 16) . chr($value >> 24));
+        } else {
+            return (chr($value >> 24) . chr($value >> 16) . chr($value >> 8) . chr($value));
+        }
+    }
+
+    /**
+     * Extract an unsigned byte from a string of bytes.
+     *
+     * @param string $bytes
+     *            the bytes.
+     *
+     * @param integer $offset
+     *            The byte found at the offset will be
+     *            returned as an integer. The must be at least one byte available
+     *            at offset.
+     *
+     * @return integer $offset the unsigned byte found at offset, e.g., an integer
+     *         in the range 0 to 255.
+     */
+    public static function bytesToByte($bytes, $offset)
+    {
+        return ord($bytes{$offset});
+    }
+
+    /**
+     * Extract a signed byte from bytes.
+     *
+     * @param string $bytes
+     *            the bytes.
+     *
+     * @param integer $offset
+     *            the offset. The byte found at the offset will be
+     *            returned as an integer. The must be at least one byte available
+     *            at offset.
+     *
+     * @return integer the signed byte found at offset, e.g., an integer in
+     *         the range -128 to 127.
+     */
+    public static function bytesToSByte($bytes, $offset)
+    {
+        $n = self::bytesToByte($bytes, $offset);
+        if ($n > 127) {
+            return $n - 256;
+        } else {
+            return $n;
+        }
+    }
+
+    /**
+     * Extract an unsigned short from bytes.
+     *
+     * @param string $bytes
+     *            the bytes.
+     *
+     * @param integer $offset
+     *            the offset. The short found at the offset will be
+     *            returned as an integer. There must be at least two bytes
+     *            available beginning at the offset given.
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     * @return integer the unsigned short found at offset, e.g., an integer
+     *         in the range 0 to 65535.
+     *
+     */
+    public static function bytesToShort($bytes, $offset, $endian)
+    {
+        if ($endian == self::LITTLE_ENDIAN) {
+            return (ord($bytes{$offset + 1}) * 256 + ord($bytes{$offset}));
+        } else {
+            return (ord($bytes{$offset}) * 256 + ord($bytes{$offset + 1}));
+        }
+    }
+
+    /**
+     * Extract a signed short from bytes.
+     *
+     * @param string $bytes
+     *
+     * @param integer $offset
+     *            The short found at offset will be returned
+     *            as an integer. There must be at least two bytes available
+     *            beginning at the offset given.
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     * @return integer the signed byte found at offset, e.g., an integer in
+     *         the range -32768 to 32767.
+     *
+     */
+    public static function bytesToSShort($bytes, $offset, $endian)
+    {
+        $n = self::bytesToShort($bytes, $offset, $endian);
+        if ($n > 32767) {
+            return $n - 65536;
+        } else {
+            return $n;
+        }
+    }
+
+    /**
+     * Extract an unsigned long from bytes.
+     *
+     * @param string $bytes
+     *
+     * @param integer $offset
+     *            The long found at offset will be returned
+     *            as an integer. There must be at least four bytes available
+     *            beginning at the offset given.
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     * @return integer the unsigned long found at offset, e.g., an integer
+     *         in the range 0 to 4294967295.
+     *
+     */
+    public static function bytesToLong($bytes, $offset, $endian)
+    {
+        if ($endian == self::LITTLE_ENDIAN) {
+            return (ord($bytes{$offset + 3}) * 16777216 + ord($bytes{$offset + 2}) * 65536 +
+                 ord($bytes{$offset + 1}) * 256 + ord($bytes{$offset}));
+        } else {
+            return (ord($bytes{$offset}) * 16777216 + ord($bytes{$offset + 1}) * 65536 + ord($bytes{$offset + 2}) * 256 +
+                 ord($bytes{$offset + 3}));
+        }
+    }
+
+    /**
+     * Extract a signed long from bytes.
+     *
+     * @param string $bytes
+     *
+     * @param integer $offset
+     *            The long found at offset will be returned
+     *            as an integer. There must be at least four bytes available
+     *            beginning at the offset given.
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}. *
+     * @return integer the signed long found at offset, e.g., an integer in
+     *         the range -2147483648 to 2147483647.
+     *
+     */
+    public static function bytesToSLong($bytes, $offset, $endian)
+    {
+        $n = self::bytesToLong($bytes, $offset, $endian);
+        if ($n > 2147483647) {
+            return $n - 4294967296;
+        } else {
+            return $n;
+        }
+    }
+
+    /**
+     * Extract an unsigned rational from bytes.
+     *
+     * @param string $bytes
+     *
+     * @param integer $offset
+     *            The rational found at offset will be
+     *            returned as an array. There must be at least eight bytes
+     *            available beginning at the offset given.
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}. *
+     * @return array the unsigned rational found at offset, e.g., an
+     *         array with two integers in the range 0 to 4294967295.
+     *
+     */
+    public static function bytesToRational($bytes, $offset, $endian)
+    {
+        return array(
+            self::bytesToLong($bytes, $offset, $endian),
+            self::bytesToLong($bytes, $offset + 4, $endian)
+        );
+    }
+
+    /**
+     * Extract a signed rational from bytes.
+     *
+     * @param string $bytes
+     *
+     * @param integer $offset
+     *            The rational found at offset will be
+     *            returned as an array. There must be at least eight bytes
+     *            available beginning at the offset given.
+     * @param integer $endian
+     *            one of {@link LITTLE_ENDIAN} and {@link
+     *            BIG_ENDIAN}.
+     * @return array the signed rational found at offset, e.g., an array
+     *         with two integers in the range -2147483648 to 2147483647.
+     *
+     */
+    public static function bytesToSRational($bytes, $offset, $endian)
+    {
+        return array(
+            self::bytesToSLong($bytes, $offset, $endian),
+            self::bytesToSLong($bytes, $offset + 4, $endian)
+        );
+    }
+
+    /**
+     * Format bytes for dumping.
+     *
+     * This method is for debug output, it will format a string as a
+     * hexadecimal dump suitable for display on a terminal. The output
+     * is printed directly to standard out.
+     *
+     * @param string $bytes
+     *            the bytes that will be dumped.
+     *
+     * @param integer $max
+     *            the maximum number of bytes to dump. If this is left
+     *            out (or left to the default of 0), then the entire string will be
+     *            dumped.
+     * @return void
+     */
+    public static function bytesToDump($bytes, $max = 0)
+    {
+        $s = strlen($bytes);
+
+        if ($max > 0) {
+            $s = min($max, $s);
+        }
+        $line = 24;
+
+        for ($i = 0; $i < $s; $i ++) {
+            printf('%02X ', ord($bytes{$i}));
+
+            if (($i + 1) % $line == 0) {
+                print("\n");
+            }
+        }
+        print("\n");
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindow.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindow.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1d10e5f3d53d9614c7cae9618040ec64c4568f2
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindow.php
@@ -0,0 +1,567 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * The window.
+ *
+ * @package PEL
+ */
+class PelDataWindow
+{
+
+    /**
+     * The data held by this window.
+     *
+     * The string can contain any kind of data, including binary data.
+     *
+     * @var string
+     */
+    private $data = '';
+
+    /**
+     * The byte order currently in use.
+     *
+     * This will be the byte order used when data is read using the for
+     * example the {@link getShort} function. It must be one of {@link
+     * PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}.
+     *
+     * @var PelByteOrder
+     * @see setByteOrder, getByteOrder
+     */
+    private $order;
+
+    /**
+     * The start of the current window.
+     *
+     * All offsets used for access into the data will count from this
+     * offset, effectively limiting access to a window starting at this
+     * byte.
+     *
+     * @var int
+     * @see setWindowStart
+     */
+    private $start = 0;
+
+    /**
+     * The size of the current window.
+     *
+     * All offsets used for access into the data will be limited by this
+     * variable. A valid offset must be strictly less than this
+     * variable.
+     *
+     * @var int
+     * @see setWindowSize
+     */
+    private $size = 0;
+
+    /**
+     * Construct a new data window with the data supplied.
+     *
+     * @param mixed $data
+     *            the data that this window will contain. This can
+     *            either be given as a string (interpreted litteraly as a sequence
+     *            of bytes) or a PHP image resource handle. The data will be copied
+     *            into the new data window.
+     *
+     * @param boolean $endianess
+     *            the initial byte order of the window. This must
+     *            be either {@link PelConvert::LITTLE_ENDIAN} or {@link
+     *            PelConvert::BIG_ENDIAN}. This will be used when integers are
+     *            read from the data, and it can be changed later with {@link
+     *            setByteOrder()}.
+     */
+    public function __construct($data = '', $endianess = PelConvert::LITTLE_ENDIAN)
+    {
+        if (is_string($data)) {
+            $this->data = $data;
+        } elseif (is_resource($data) && get_resource_type($data) == 'gd') {
+            /*
+             * The ImageJpeg() function insists on printing the bytes
+             * instead of returning them in a more civil way as a string, so
+             * we have to buffer the output...
+             */
+            ob_start();
+            ImageJpeg($data, null, Pel::getJPEGQuality());
+            $this->data = ob_get_clean();
+        } else {
+            throw new PelInvalidArgumentException('Bad type for $data: %s', gettype($data));
+        }
+
+        $this->order = $endianess;
+        $this->size = strlen($this->data);
+    }
+
+    /**
+     * Get the size of the data window.
+     *
+     * @return integer the number of bytes covered by the window. The
+     *         allowed offsets go from 0 up to this number minus one.
+     *
+     * @see getBytes()
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * Change the byte order of the data.
+     *
+     * @param integer $order
+     *            the new byte order. This must be either
+     *            {@link PelConvert::LITTLE_ENDIAN} or {@link
+     *            PelConvert::BIG_ENDIAN}.
+     */
+    public function setByteOrder($order)
+    {
+        $this->order = $order;
+    }
+
+    /**
+     * Get the currently used byte order.
+     *
+     * @return integer this will be either {@link
+     *         PelConvert::LITTLE_ENDIAN} or {@link PelConvert::BIG_ENDIAN}.
+     */
+    public function getByteOrder()
+    {
+        return $this->order;
+    }
+
+    /**
+     * Move the start of the window forward.
+     *
+     * @param integer $start
+     *            the new start of the window. All new offsets will be
+     *            calculated from this new start offset, and the size of the window
+     *            will shrink to keep the end of the window in place.
+     */
+    public function setWindowStart($start)
+    {
+        if ($start < 0 || $start > $this->size) {
+            throw new PelDataWindowWindowException(
+                'Window [%d, %d] does ' . 'not fit in window [0, %d]',
+                $start,
+                $this->size,
+                $this->size);
+        }
+        $this->start += $start;
+        $this->size -= $start;
+    }
+
+    /**
+     * Adjust the size of the window.
+     * The size can only be made smaller.
+     *
+     * @param integer $size
+     *            the desired size of the window. If the argument is
+     *            negative, the window will be shrunk by the argument.
+     */
+    public function setWindowSize($size)
+    {
+        if ($size < 0) {
+            $size += $this->size;
+        }
+        if ($size < 0 || $size > $this->size) {
+            throw new PelDataWindowWindowException(
+                'Window [0, %d] ' . 'does not fit in window [0, %d]',
+                $size,
+                $this->size);
+        }
+        $this->size = $size;
+    }
+
+    /**
+     * Make a new data window with the same data as the this window.
+     *
+     * @param integer|NULL $start
+     *            if an integer is supplied, then it will be the start
+     *            of the window in the clone. If left unspecified, then the clone
+     *            will inherit the start from this object.
+     *
+     * @param integer|NULL $size
+     *            if an integer is supplied, then it will be the size
+     *            of the window in the clone. If left unspecified, then the clone
+     *            will inherit the size from this object.
+     *
+     * @return PelDataWindow a new window that operates on the same data
+     *         as this window, but (optionally) with a smaller window size.
+     */
+    public function getClone($start = null, $size = null)
+    {
+        $c = clone $this;
+
+        if (is_int($start)) {
+            $c->setWindowStart($start);
+        }
+        if (is_int($size)) {
+            $c->setWindowSize($size);
+        }
+        return $c;
+    }
+
+    /**
+     * Validate an offset against the current window.
+     *
+     * @param integer $offset
+     *            the offset to be validated. If the offset is negative
+     *            or if it is greater than or equal to the current window size,
+     *            then a {@link PelDataWindowOffsetException} is thrown.
+     *
+     * @return void if the offset is valid nothing is returned, if it is
+     *         invalid a new {@link PelDataWindowOffsetException} is thrown.
+     * @throws PelDataWindowOffsetException
+     */
+    private function validateOffset($offset)
+    {
+        if ($offset < 0 || $offset >= $this->size) {
+            throw new PelDataWindowOffsetException('Offset %d not within [%d, %d]', $offset, 0, $this->size - 1);
+        }
+    }
+
+    /**
+     * Return some or all bytes visible in the window.
+     *
+     * This method works just like the standard {@link substr()}
+     * function in PHP with the exception that it works within the
+     * window of accessible bytes and does strict range checking.
+     *
+     * @param integer|NULL $start
+     *            the offset to the first byte returned. If a negative
+     *            number is given, then the counting will be from the end of the
+     *            window. Invalid offsets will result in a {@link
+     *            PelDataWindowOffsetException} being thrown.
+     *
+     * @param integer|NUL $size
+     *            the size of the sub-window. If a negative number is
+     *            given, then that many bytes will be omitted from the result.
+     *
+     * @return string a subset of the bytes in the window. This will
+     *         always return no more than {@link getSize()} bytes.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getBytes($start = null, $size = null)
+    {
+        if (is_int($start)) {
+            if ($start < 0) {
+                $start += $this->size;
+            }
+
+            $this->validateOffset($start);
+        } else {
+            $start = 0;
+        }
+
+        if (is_int($size)) {
+            if ($size <= 0) {
+                $size += $this->size - $start;
+            }
+
+            $this->validateOffset($start + $size);
+        } else {
+            $size = $this->size - $start;
+        }
+
+        return substr($this->data, $this->start + $start, $size);
+    }
+
+    /**
+     * Return an unsigned byte from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first byte in the current allowed window. The last
+     *            valid offset is equal to {@link getSize()}-1. Invalid offsets
+     *            will result in a {@link PelDataWindowOffsetException} being
+     *            thrown.
+     *
+     * @return integer the unsigned byte found at offset.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getByte($offset = 0)
+    {
+        /*
+         * Validate the offset --- this throws an exception if offset is
+         * out of range.
+         */
+        $this->validateOffset($offset);
+
+        /* Translate the offset into an offset into the data. */
+        $offset += $this->start;
+
+        /* Return an unsigned byte. */
+        return PelConvert::bytesToByte($this->data, $offset);
+    }
+
+    /**
+     * Return a signed byte from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first byte in the current allowed window. The last
+     *            valid offset is equal to {@link getSize()}-1. Invalid offsets
+     *            will result in a {@link PelDataWindowOffsetException} being
+     *            thrown.
+     *
+     * @return integer the signed byte found at offset.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getSByte($offset = 0)
+    {
+        /*
+         * Validate the offset --- this throws an exception if offset is
+         * out of range.
+         */
+        $this->validateOffset($offset);
+
+        /* Translate the offset into an offset into the data. */
+        $offset += $this->start;
+
+        /* Return a signed byte. */
+        return PelConvert::bytesToSByte($this->data, $offset);
+    }
+
+    /**
+     * Return an unsigned short read from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first short available in the current allowed window.
+     *            The last valid offset is equal to {@link getSize()}-2. Invalid
+     *            offsets will result in a {@link PelDataWindowOffsetException}
+     *            being thrown.
+     *
+     * @return integer the unsigned short found at offset.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getShort($offset = 0)
+    {
+        /*
+         * Validate the offset+1 to see if we can safely get two bytes ---
+         * this throws an exception if offset is out of range.
+         */
+        $this->validateOffset($offset);
+        $this->validateOffset($offset + 1);
+
+        /* Translate the offset into an offset into the data. */
+        $offset += $this->start;
+
+        /* Return an unsigned short. */
+        return PelConvert::bytesToShort($this->data, $offset, $this->order);
+    }
+
+    /**
+     * Return a signed short read from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first short available in the current allowed window.
+     *            The last valid offset is equal to {@link getSize()}-2. Invalid
+     *            offsets will result in a {@link PelDataWindowOffsetException}
+     *            being thrown.
+     *
+     * @return integer the signed short found at offset.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getSShort($offset = 0)
+    {
+        /*
+         * Validate the offset+1 to see if we can safely get two bytes ---
+         * this throws an exception if offset is out of range.
+         */
+        $this->validateOffset($offset);
+        $this->validateOffset($offset + 1);
+
+        /* Translate the offset into an offset into the data. */
+        $offset += $this->start;
+
+        /* Return a signed short. */
+        return PelConvert::bytesToSShort($this->data, $offset, $this->order);
+    }
+
+    /**
+     * Return an unsigned long read from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first long available in the current allowed window.
+     *            The last valid offset is equal to {@link getSize()}-4. Invalid
+     *            offsets will result in a {@link PelDataWindowOffsetException}
+     *            being thrown.
+     *
+     * @return integer the unsigned long found at offset.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getLong($offset = 0)
+    {
+        /*
+         * Validate the offset+3 to see if we can safely get four bytes
+         * --- this throws an exception if offset is out of range.
+         */
+        $this->validateOffset($offset);
+        $this->validateOffset($offset + 3);
+
+        /* Translate the offset into an offset into the data. */
+        $offset += $this->start;
+
+        /* Return an unsigned long. */
+        return PelConvert::bytesToLong($this->data, $offset, $this->order);
+    }
+
+    /**
+     * Return a signed long read from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first long available in the current allowed window.
+     *            The last valid offset is equal to {@link getSize()}-4. Invalid
+     *            offsets will result in a {@link PelDataWindowOffsetException}
+     *            being thrown.
+     *
+     * @return integer the signed long found at offset.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getSLong($offset = 0)
+    {
+        /*
+         * Validate the offset+3 to see if we can safely get four bytes
+         * --- this throws an exception if offset is out of range.
+         */
+        $this->validateOffset($offset);
+        $this->validateOffset($offset + 3);
+
+        /* Translate the offset into an offset into the data. */
+        $offset += $this->start;
+
+        /* Return a signed long. */
+        return PelConvert::bytesToSLong($this->data, $offset, $this->order);
+    }
+
+    /**
+     * Return an unsigned rational read from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first rational available in the current allowed
+     *            window. The last valid offset is equal to {@link getSize()}-8.
+     *            Invalid offsets will result in a {@link
+     *            PelDataWindowOffsetException} being thrown.
+     *
+     * @return array the unsigned rational found at offset. A rational
+     *         number is represented as an array of two numbers: the enumerator
+     *         and denominator. Both of these numbers will be unsigned longs.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getRational($offset = 0)
+    {
+        return array(
+            $this->getLong($offset),
+            $this->getLong($offset + 4)
+        );
+    }
+
+    /**
+     * Return a signed rational read from the data.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will
+     *            return the first rational available in the current allowed
+     *            window. The last valid offset is equal to {@link getSize()}-8.
+     *            Invalid offsets will result in a {@link
+     *            PelDataWindowOffsetException} being thrown.
+     *
+     * @return array the signed rational found at offset. A rational
+     *         number is represented as an array of two numbers: the enumerator
+     *         and denominator. Both of these numbers will be signed longs.
+     * @throws PelDataWindowOffsetException
+     */
+    public function getSRational($offset = 0)
+    {
+        return array(
+            $this->getSLong($offset),
+            $this->getSLong($offset + 4)
+        );
+    }
+
+    /**
+     * String comparison on substrings.
+     *
+     * @param integer $offset
+     *            the offset into the data. An offset of zero will make
+     *            the comparison start with the very first byte available in the
+     *            window. The last valid offset is equal to {@link getSize()}
+     *            minus the length of the string. If the string is too long, then
+     *            a {@link PelDataWindowOffsetException} will be thrown.
+     *
+     * @param string $str
+     *            the string to compare with.
+     *
+     * @return boolean true if the string given matches the data in the
+     *         window, at the specified offset, false otherwise. The comparison
+     *         will stop as soon as a mismatch if found.
+     * @throws PelDataWindowOffsetException
+     */
+    public function strcmp($offset, $str)
+    {
+        /*
+         * Validate the offset of the final character we might have to
+         * check.
+         */
+        $s = strlen($str);
+        $this->validateOffset($offset);
+        $this->validateOffset($offset + $s - 1);
+
+        /* Translate the offset into an offset into the data. */
+        $offset += $this->start;
+
+        /* Check each character, return as soon as the answer is known. */
+        for ($i = 0; $i < $s; $i ++) {
+            if ($this->data{$offset + $i} != $str{$i}) {
+                return false;
+            }
+        }
+
+        /* All characters matches each other, return true. */
+        return true;
+    }
+
+    /**
+     * Return a string representation of the data window.
+     *
+     * @return string a description of the window with information about
+     *         the number of bytes accessible, the total number of bytes, and
+     *         the window start and stop.
+     */
+    public function __toString()
+    {
+        return Pel::fmt(
+            'DataWindow: %d bytes in [%d, %d] of %d bytes',
+            $this->size,
+            $this->start,
+            $this->start + $this->size,
+            strlen($this->data));
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindowOffsetException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindowOffsetException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ec3d8dad40290a47b8a2e9f56dffde35a5e1165
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindowOffsetException.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * An exception thrown when an invalid offset is encountered.
+ *
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelDataWindowOffsetException extends PelException
+{
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindowWindowException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindowWindowException.php
new file mode 100644
index 0000000000000000000000000000000000000000..4ad4c6e0e811731c6e644855a5c65e1615a1288b
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelDataWindowWindowException.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * A container for bytes with a limited window of accessible bytes.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL)
+ * @package PEL
+ */
+
+/**
+ * An exception thrown when an invalid window is encountered.
+ *
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelDataWindowWindowException extends PelException
+{
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntry.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntry.php
new file mode 100644
index 0000000000000000000000000000000000000000..75781bde73c20df01d983bf66dbf713edb2cbf87
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntry.php
@@ -0,0 +1,253 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif entries.
+ *
+ * This file defines two exception classes and the abstract class
+ * {@link PelEntry} which provides the basic methods that all Exif
+ * entries will have. All Exif entries will be represented by
+ * descendants of the {@link PelEntry} class --- the class itself is
+ * abstract and so it cannot be instantiated.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Common ancestor class of all {@link PelIfd} entries.
+ *
+ * As this class is abstract you cannot instantiate objects from it.
+ * It only serves as a common ancestor to define the methods common to
+ * all entries. The most important methods are {@link getValue()} and
+ * {@link setValue()}, both of which is abstract in this class. The
+ * descendants will give concrete implementations for them.
+ *
+ * If you have some data coming from an image (some raw bytes), then
+ * the static method {@link newFromData()} is helpful --- it will look
+ * at the data and give you a proper decendent of {@link PelEntry}
+ * back.
+ *
+ * If you instead want to have an entry for some data which take the
+ * form of an integer, a string, a byte, or some other PHP type, then
+ * don't use this class. You should instead create an object of the
+ * right subclass ({@link PelEntryShort} for short integers, {@link
+ * PelEntryAscii} for strings, and so on) directly.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+abstract class PelEntry
+{
+
+    /**
+     * Type of IFD containing this tag.
+     *
+     * This must be one of the constants defined in {@link PelIfd}:
+     * {@link PelIfd::IFD0} for the main image IFD, {@link PelIfd::IFD1}
+     * for the thumbnail image IFD, {@link PelIfd::EXIF} for the Exif
+     * sub-IFD, {@link PelIfd::GPS} for the GPS sub-IFD, or {@link
+     * PelIfd::INTEROPERABILITY} for the interoperability sub-IFD.
+     *
+     * @var int
+     */
+    protected $ifd_type;
+
+    /**
+     * The bytes representing this entry.
+     *
+     * Subclasses must either override {@link getBytes()} or, if
+     * possible, maintain this property so that it always contains a
+     * true representation of the entry.
+     *
+     * @var string
+     */
+    protected $bytes = '';
+
+    /**
+     * The {@link PelTag} of this entry.
+     *
+     * @var PelTag
+     */
+    protected $tag;
+
+    /**
+     * The {@link PelFormat} of this entry.
+     *
+     * @var PelFormat
+     */
+    protected $format;
+
+    /**
+     * The number of components of this entry.
+     *
+     * @var int
+     */
+    protected $components;
+
+    /**
+     * Return the tag of this entry.
+     *
+     * @return PelTag the tag of this entry.
+     */
+    public function getTag()
+    {
+        return $this->tag;
+    }
+
+    /**
+     * Return the type of IFD which holds this entry.
+     *
+     * @return int one of the constants defined in {@link PelIfd}:
+     *         {@link PelIfd::IFD0} for the main image IFD, {@link PelIfd::IFD1}
+     *         for the thumbnail image IFD, {@link PelIfd::EXIF} for the Exif
+     *         sub-IFD, {@link PelIfd::GPS} for the GPS sub-IFD, or {@link
+     *         PelIfd::INTEROPERABILITY} for the interoperability sub-IFD.
+     */
+    public function getIfdType()
+    {
+        return $this->ifd_type;
+    }
+
+    /**
+     * Update the IFD type.
+     *
+     * @param
+     *            int must be one of the constants defined in {@link
+     *            PelIfd}: {@link PelIfd::IFD0} for the main image IFD, {@link
+     *            PelIfd::IFD1} for the thumbnail image IFD, {@link PelIfd::EXIF}
+     *            for the Exif sub-IFD, {@link PelIfd::GPS} for the GPS sub-IFD, or
+     *            {@link PelIfd::INTEROPERABILITY} for the interoperability
+     *            sub-IFD.
+     */
+    public function setIfdType($type)
+    {
+        $this->ifd_type = $type;
+    }
+
+    /**
+     * Return the format of this entry.
+     *
+     * @return PelFormat the format of this entry.
+     */
+    public function getFormat()
+    {
+        return $this->format;
+    }
+
+    /**
+     * Return the number of components of this entry.
+     *
+     * @return int the number of components of this entry.
+     */
+    public function getComponents()
+    {
+        return $this->components;
+    }
+
+    /**
+     * Turn this entry into bytes.
+     *
+     * @param
+     *            PelByteOrder the desired byte order, which must be either
+     *            {@link Convert::LITTLE_ENDIAN} or {@link Convert::BIG_ENDIAN}.
+     *
+     * @return string bytes representing this entry.
+     */
+    public function getBytes($o)
+    {
+        return $this->bytes;
+    }
+
+    /**
+     * Get the value of this entry as text.
+     *
+     * The value will be returned in a format suitable for presentation,
+     * e.g., rationals will be returned as 'x/y', ASCII strings will be
+     * returned as themselves etc.
+     *
+     * @param
+     *            boolean some values can be returned in a long or more
+     *            brief form, and this parameter controls that.
+     *
+     * @return string the value as text.
+     */
+    abstract public function getText($brief = false);
+
+    /**
+     * Get the value of this entry.
+     *
+     * The value returned will generally be the same as the one supplied
+     * to the constructor or with {@link setValue()}. For a formatted
+     * version of the value, one should use {@link getText()} instead.
+     *
+     * @return mixed the unformatted value.
+     */
+    abstract public function getValue();
+
+    /**
+     * Set the value of this entry.
+     *
+     * The value should be in the same format as for the constructor.
+     *
+     * @param
+     *            mixed the new value.
+     *
+     * @abstract
+     *
+     */
+    public function setValue($value)
+    {
+        /*
+         * This (fake) abstract method is here to make it possible for the
+         * documentation to refer to PelEntry::setValue().
+         * It cannot declared abstract in the proper PHP way, for then PHP
+         * wont allow subclasses to define it with two arguments (which is
+         * what PelEntryCopyright does).
+         */
+        throw new PelException('setValue() is abstract.');
+    }
+
+    /**
+     * Turn this entry into a string.
+     *
+     * @return string a string representation of this entry. This is
+     *         mostly for debugging.
+     */
+    public function __toString()
+    {
+        $str = Pel::fmt("  Tag: 0x%04X (%s)\n", $this->tag, PelTag::getName($this->ifd_type, $this->tag));
+        $str .= Pel::fmt("    Format    : %d (%s)\n", $this->format, PelFormat::getName($this->format));
+        $str .= Pel::fmt("    Components: %d\n", $this->components);
+        if ($this->getTag() != PelTag::MAKER_NOTE && $this->getTag() != PelTag::PRINT_IM) {
+            $str .= Pel::fmt("    Value     : %s\n", print_r($this->getValue(), true));
+        }
+        $str .= Pel::fmt("    Text      : %s\n", $this->getText());
+        return $str;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryAscii.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryAscii.php
new file mode 100644
index 0000000000000000000000000000000000000000..39d84fb4535fea58724296eb5fb4d459a59a5b4e
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryAscii.php
@@ -0,0 +1,142 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold ASCII strings.
+ *
+ * The classes defined here are to be used for Exif entries holding
+ * ASCII strings, such as {@link PelTag::MAKE}, {@link
+ * PelTag::SOFTWARE}, and {@link PelTag::DATE_TIME}. For
+ * entries holding normal textual ASCII strings the class {@link
+ * PelEntryAscii} should be used, but for entries holding
+ * timestamps the class {@link PelEntryTime} would be more
+ * convenient instead. Copyright information is handled by the {@link
+ * PelEntryCopyright} class.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding a plain ASCII string.
+ *
+ * This class can hold a single ASCII string, and it will be used as in
+ * <code>
+ * $entry = $ifd->getEntry(PelTag::IMAGE_DESCRIPTION);
+ * print($entry->getValue());
+ * $entry->setValue('This is my image. I like it.');
+ * </code>
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryAscii extends PelEntry
+{
+
+    /**
+     * The string hold by this entry.
+     *
+     * This is the string that was given to the {@link __construct
+     * constructor} or later to {@link setValue}, without any final NULL
+     * character.
+     *
+     * @var string
+     */
+    private $str;
+
+    /**
+     * Make a new PelEntry that can hold an ASCII string.
+     *
+     * @param int $tag
+     *            the tag which this entry represents. This should be
+     *            one of the constants defined in {@link PelTag}, e.g., {@link
+     *            PelTag::IMAGE_DESCRIPTION}, {@link PelTag::MODEL}, or any other
+     *            tag with format {@link PelFormat::ASCII}.
+     *
+     * @param string $str
+     *            the string that this entry will represent. The
+     *            string must obey the same rules as the string argument to {@link
+     *            setValue}, namely that it should be given without any trailing
+     *            NULL character and that it must be plain 7-bit ASCII.
+     */
+    public function __construct($tag, $str = '')
+    {
+        $this->tag = $tag;
+        $this->format = PelFormat::ASCII;
+        self::setValue($str);
+    }
+
+    /**
+     * Give the entry a new ASCII value.
+     *
+     * This will overwrite the previous value. The value can be
+     * retrieved later with the {@link getValue} method.
+     *
+     * @param
+     *            string the new value of the entry. This should be given
+     *            without any trailing NULL character. The string must be plain
+     *            7-bit ASCII, the string should contain no high bytes.
+     *
+     * @todo Implement check for high bytes?
+     */
+    public function setValue($str)
+    {
+        $this->components = strlen($str) + 1;
+        $this->str = $str;
+        $this->bytes = $str . chr(0x00);
+    }
+
+    /**
+     * Return the ASCII string of the entry.
+     *
+     * @return string the string held, without any final NULL character.
+     *         The string will be the same as the one given to {@link setValue}
+     *         or to the {@link __construct constructor}.
+     */
+    public function getValue()
+    {
+        return $this->str;
+    }
+
+    /**
+     * Return the ASCII string of the entry.
+     *
+     * This methods returns the same as {@link getValue}.
+     *
+     * @param
+     *            boolean not used with ASCII entries.
+     *
+     * @return string the string held, without any final NULL character.
+     *         The string will be the same as the one given to {@link setValue}
+     *         or to the {@link __construct constructor}.
+     */
+    public function getText($brief = false)
+    {
+        return $this->str;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryByte.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryByte.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac736c118bc6b681736553c2a1e02e2ca0533e40
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryByte.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold bytes, both signed and unsigned.
+ * The {@link
+ * PelEntryWindowsString} class is used to manipulate strings in the
+ * format Windows XP needs.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding unsigned bytes.
+ *
+ * This class can hold bytes, either just a single byte or an array of
+ * bytes. The class will be used to manipulate any of the Exif tags
+ * which has format {@link PelFormat::BYTE}.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryByte extends PelEntryNumber
+{
+
+    /**
+     * Make a new entry that can hold an unsigned byte.
+     *
+     * The method accept several integer arguments. The {@link
+     * getValue} method will always return an array except for when a
+     * single integer argument is given here.
+     *
+     * @param PelTag $tag
+     *            the tag which this entry represents. This
+     *            should be one of the constants defined in {@link PelTag}
+     *            which has format {@link PelFormat::BYTE}.
+     *
+     * @param int $value...
+     *            the byte(s) that this entry will represent.
+     *            The argument passed must obey the same rules as the argument to
+     *            {@link setValue}, namely that it should be within range of an
+     *            unsigned byte, that is between 0 and 255 (inclusive). If not,
+     *            then a {@link PelOverflowException} will be thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->min = 0;
+        $this->max = 255;
+        $this->format = PelFormat::BYTE;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Convert a number into bytes.
+     *
+     * @param int $number
+     *            the number that should be converted.
+     *
+     * @param PelByteOrder $order
+     *            one of {@link PelConvert::LITTLE_ENDIAN} and
+     *            {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
+     *
+     * @return string bytes representing the number given.
+     */
+    public function numberToBytes($number, $order)
+    {
+        return chr($number);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryCopyright.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryCopyright.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb8f20988e1073862a9b38116594227fae26dc4f
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryCopyright.php
@@ -0,0 +1,191 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold ASCII strings.
+ *
+ * The classes defined here are to be used for Exif entries holding
+ * ASCII strings, such as {@link PelTag::MAKE}, {@link
+ * PelTag::SOFTWARE}, and {@link PelTag::DATE_TIME}. For
+ * entries holding normal textual ASCII strings the class {@link
+ * PelEntryAscii} should be used, but for entries holding
+ * timestamps the class {@link PelEntryTime} would be more
+ * convenient instead. Copyright information is handled by the {@link
+ * PelEntryCopyright} class.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding copyright information.
+ *
+ * The Exif standard specifies a certain format for copyright
+ * information where the one {@link PelTag::COPYRIGHT copyright
+ * tag} holds both the photographer and editor copyrights, separated
+ * by a NULL character.
+ *
+ * This class is used to manipulate that tag so that the format is
+ * kept to the standard. A common use would be to add a new copyright
+ * tag to an image, since most cameras do not add this tag themselves.
+ * This would be done like this:
+ *
+ * <code>
+ * $entry = new PelEntryCopyright('Copyright, Martin Geisler, 2004');
+ * $ifd0->addEntry($entry);
+ * </code>
+ *
+ * Here we only set the photographer copyright, use the optional
+ * second argument to specify the editor copyright. If there is only
+ * an editor copyright, then let the first argument be the empty
+ * string.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryCopyright extends PelEntryAscii
+{
+
+    /**
+     * The photographer copyright.
+     *
+     * @var string
+     */
+    private $photographer;
+
+    /**
+     * The editor copyright.
+     *
+     * @var string
+     */
+    private $editor;
+
+    /**
+     * Make a new entry for holding copyright information.
+     *
+     * @param
+     *            string the photographer copyright. Use the empty string
+     *            if there is no photographer copyright.
+     *
+     * @param
+     *            string the editor copyright. Use the empty string if
+     *            there is no editor copyright.
+     */
+    public function __construct($photographer = '', $editor = '')
+    {
+        parent::__construct(PelTag::COPYRIGHT);
+        $this->setValue($photographer, $editor);
+    }
+
+    /**
+     * Update the copyright information.
+     *
+     * @param
+     *            string the photographer copyright. Use the empty string
+     *            if there is no photographer copyright.
+     *
+     * @param
+     *            string the editor copyright. Use the empty string if
+     *            there is no editor copyright.
+     */
+    public function setValue($photographer = '', $editor = '')
+    {
+        $this->photographer = $photographer;
+        $this->editor = $editor;
+
+        if ($photographer == '' && $editor != '') {
+            $photographer = ' ';
+        }
+
+        if ($editor == '') {
+            parent::setValue($photographer);
+        } else {
+            parent::setValue($photographer . chr(0x00) . $editor);
+        }
+    }
+
+    /**
+     * Retrive the copyright information.
+     *
+     * The strings returned will be the same as the one used previously
+     * with either {@link __construct the constructor} or with {@link
+     * setValue}.
+     *
+     * @return array an array with two strings, the photographer and
+     *         editor copyrights. The two fields will be returned in that
+     *         order, so that the first array index will be the photographer
+     *         copyright, and the second will be the editor copyright.
+     */
+    public function getValue()
+    {
+        return array(
+            $this->photographer,
+            $this->editor
+        );
+    }
+
+    /**
+     * Return a text string with the copyright information.
+     *
+     * The photographer and editor copyright fields will be returned
+     * with a '-' in between if both copyright fields are present,
+     * otherwise only one of them will be returned.
+     *
+     * @param
+     *            boolean if false, then the strings '(Photographer)' and
+     *            '(Editor)' will be appended to the photographer and editor
+     *            copyright fields (if present), otherwise the fields will be
+     *            returned as is.
+     *
+     * @return string the copyright information in a string.
+     */
+    public function getText($brief = false)
+    {
+        if ($brief) {
+            $p = '';
+            $e = '';
+        } else {
+            $p = ' ' . Pel::tra('(Photographer)');
+            $e = ' ' . Pel::tra('(Editor)');
+        }
+
+        if ($this->photographer != '' && $this->editor != '') {
+            return $this->photographer . $p . ' - ' . $this->editor . $e;
+        }
+
+        if ($this->photographer != '') {
+            return $this->photographer . $p;
+        }
+
+        if ($this->editor != '') {
+            return $this->editor . $e;
+        }
+
+        return '';
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a13ebf5912e4ac8c89b846b5a5a2f95f32f870c9
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryException.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif entries.
+ *
+ * This file defines two exception classes and the abstract class
+ * {@link PelEntry} which provides the basic methods that all Exif
+ * entries will have. All Exif entries will be represented by
+ * descendants of the {@link PelEntry} class --- the class itself is
+ * abstract and so it cannot be instantiated.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Exception indicating a problem with an entry.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelEntryException extends PelException
+{
+
+    /**
+     * The IFD type (if known).
+     *
+     * @var int
+     */
+    protected $type;
+
+    /**
+     * The tag of the entry (if known).
+     *
+     * @var PelTag
+     */
+    protected $tag;
+
+    /**
+     * Get the IFD type associated with the exception.
+     *
+     * @return int one of {@link PelIfd::IFD0}, {@link PelIfd::IFD1},
+     *         {@link PelIfd::EXIF}, {@link PelIfd::GPS}, or {@link
+     *         PelIfd::INTEROPERABILITY}. If no type is set, null is returned.
+     */
+    public function getIfdType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Get the tag associated with the exception.
+     *
+     * @return PelTag the tag. If no tag is set, null is returned.
+     */
+    public function getTag()
+    {
+        return $this->tag;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryLong.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryLong.php
new file mode 100644
index 0000000000000000000000000000000000000000..dead1efe283cc0a7c2abd1b4e3291e81d869da7f
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryLong.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold longs, both signed and unsigned.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding unsigned longs.
+ *
+ * This class can hold longs, either just a single long or an array of
+ * longs. The class will be used to manipulate any of the Exif tags
+ * which can have format {@link PelFormat::LONG} like in this
+ * example:
+ * <code>
+ * $w = $ifd->getEntry(PelTag::EXIF_IMAGE_WIDTH);
+ * $w->setValue($w->getValue() / 2);
+ * $h = $ifd->getEntry(PelTag::EXIF_IMAGE_HEIGHT);
+ * $h->setValue($h->getValue() / 2);
+ * </code>
+ * Here the width and height is updated to 50% of their original
+ * values.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryLong extends PelEntryNumber
+{
+
+    /**
+     * Make a new entry that can hold an unsigned long.
+     *
+     * The method accept its arguments in two forms: several integer
+     * arguments or a single array argument. The {@link getValue}
+     * method will always return an array except for when a single
+     * integer argument is given here, or when an array with just a
+     * single integer is given.
+     *
+     * This means that one can conveniently use objects like this:
+     * <code>
+     * $a = new PelEntryLong(PelTag::EXIF_IMAGE_WIDTH, 123456);
+     * $b = $a->getValue() - 654321;
+     * </code>
+     * where the call to {@link getValue} will return an integer instead
+     * of an array with one integer element, which would then have to be
+     * extracted.
+     *
+     * @param
+     *            PelTag the tag which this entry represents. This
+     *            should be one of the constants defined in {@link PelTag},
+     *            e.g., {@link PelTag::IMAGE_WIDTH}, or any other tag which can
+     *            have format {@link PelFormat::LONG}.
+     * @param int $value...
+     *            the long(s) that this entry will
+     *            represent or an array of longs. The argument passed must obey
+     *            the same rules as the argument to {@link setValue}, namely that
+     *            it should be within range of an unsigned long (32 bit), that is
+     *            between 0 and 4294967295 (inclusive). If not, then a {@link
+     *            PelExifOverflowException} will be thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->min = 0;
+        $this->max = 4294967295;
+        $this->format = PelFormat::LONG;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Convert a number into bytes.
+     *
+     * @param
+     *            int the number that should be converted.
+     * @param
+     *            PelByteOrder one of {@link PelConvert::LITTLE_ENDIAN} and
+     *            {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
+     * @return string bytes representing the number given.
+     */
+    public function numberToBytes($number, $order)
+    {
+        return PelConvert::longToBytes($number, $order);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryNumber.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryNumber.php
new file mode 100644
index 0000000000000000000000000000000000000000..e967db0e4004a5d2e79d9a513f50610fbd75977c
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryNumber.php
@@ -0,0 +1,285 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Abstract class for numbers.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding numbers.
+ *
+ * This class can hold numbers, with range checks.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+abstract class PelEntryNumber extends PelEntry
+{
+
+    /**
+     * The value held by this entry.
+     *
+     * @var array
+     */
+    protected $value = array();
+
+    /**
+     * The minimum allowed value.
+     *
+     * Any attempt to change the value below this variable will result
+     * in a {@link PelOverflowException} being thrown.
+     *
+     * @var int
+     */
+    protected $min;
+
+    /**
+     * The maximum allowed value.
+     *
+     * Any attempt to change the value over this variable will result in
+     * a {@link PelOverflowException} being thrown.
+     *
+     * @var int
+     */
+    protected $max;
+
+    /**
+     * The dimension of the number held.
+     *
+     * Normal numbers have a dimension of one, pairs have a dimension of
+     * two, etc.
+     *
+     * @var int
+     */
+    protected $dimension = 1;
+
+    /**
+     * Change the value.
+     *
+     * This method can change both the number of components and the
+     * value of the components. Range checks will be made on the new
+     * value, and a {@link PelOverflowException} will be thrown if the
+     * value is found to be outside the legal range.
+     *
+     * The method accept several number arguments. The {@link getValue}
+     * method will always return an array except for when a single
+     * number is given here.
+     *
+     * @param int|array $value...
+     *            the new value(s). This can be zero or
+     *            more numbers, that is, either integers or arrays. The input will
+     *            be checked to ensure that the numbers are within the valid range.
+     *            If not, then a {@link PelOverflowException} will be thrown.
+     *
+     * @see getValue
+     */
+    public function setValue($value)
+    {
+        $value = func_get_args();
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Change the value.
+     *
+     * This method can change both the number of components and the
+     * value of the components. Range checks will be made on the new
+     * value, and a {@link PelOverflowException} will be thrown if the
+     * value is found to be outside the legal range.
+     *
+     * @param
+     *            array the new values. The array must contain the new
+     *            numbers.
+     *
+     * @see getValue
+     */
+    public function setValueArray($value)
+    {
+        foreach ($value as $v) {
+            $this->validateNumber($v);
+        }
+
+        $this->components = count($value);
+        $this->value = $value;
+    }
+
+    /**
+     * Return the numeric value held.
+     *
+     * @return int|array this will either be a single number if there is
+     *         only one component, or an array of numbers otherwise.
+     */
+    public function getValue()
+    {
+        if ($this->components == 1) {
+            return $this->value[0];
+        } else {
+            return $this->value;
+        }
+    }
+
+    /**
+     * Validate a number.
+     *
+     * This method will check that the number given is within the range
+     * given my {@link getMin()} and {@link getMax()}, inclusive. If
+     * not, then a {@link PelOverflowException} is thrown.
+     *
+     * @param
+     *            int|array the number in question.
+     *
+     * @return void nothing, but will throw a {@link
+     *         PelOverflowException} if the number is found to be outside the
+     *         legal range and {@link Pel::$strict} is true.
+     */
+    public function validateNumber($n)
+    {
+        if ($this->dimension == 1) {
+            if ($n < $this->min || $n > $this->max) {
+                Pel::maybeThrow(new PelOverflowException($n, $this->min, $this->max));
+            }
+        } else {
+            for ($i = 0; $i < $this->dimension; $i ++) {
+                if ($n[$i] < $this->min || $n[$i] > $this->max) {
+                    Pel::maybeThrow(new PelOverflowException($n[$i], $this->min, $this->max));
+                }
+            }
+        }
+    }
+
+    /**
+     * Add a number.
+     *
+     * This appends a number to the numbers already held by this entry,
+     * thereby increasing the number of components by one.
+     *
+     * @param
+     *            int|array the number to be added.
+     */
+    public function addNumber($n)
+    {
+        $this->validateNumber($n);
+        $this->value[] = $n;
+        $this->components ++;
+    }
+
+    /**
+     * Convert a number into bytes.
+     *
+     * The concrete subclasses will have to implement this method so
+     * that the numbers represented can be turned into bytes.
+     *
+     * The method will be called once for each number held by the entry.
+     *
+     * @param
+     *            int the number that should be converted.
+     *
+     * @param
+     *            PelByteOrder one of {@link PelConvert::LITTLE_ENDIAN} and
+     *            {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
+     *
+     * @return string bytes representing the number given.
+     */
+    abstract public function numberToBytes($number, $order);
+
+    /**
+     * Turn this entry into bytes.
+     *
+     * @param
+     *            PelByteOrder the desired byte order, which must be either
+     *            {@link PelConvert::LITTLE_ENDIAN} or {@link
+     *            PelConvert::BIG_ENDIAN}.
+     *
+     * @return string bytes representing this entry.
+     */
+    public function getBytes($o)
+    {
+        $bytes = '';
+        for ($i = 0; $i < $this->components; $i ++) {
+            if ($this->dimension == 1) {
+                $bytes .= $this->numberToBytes($this->value[$i], $o);
+            } else {
+                for ($j = 0; $j < $this->dimension; $j ++) {
+                    $bytes .= $this->numberToBytes($this->value[$i][$j], $o);
+                }
+            }
+        }
+        return $bytes;
+    }
+
+    /**
+     * Format a number.
+     *
+     * This method is called by {@link getText} to format numbers.
+     * Subclasses should override this method if they need more
+     * sophisticated behavior than the default, which is to just return
+     * the number as is.
+     *
+     * @param
+     *            int the number which will be formatted.
+     *
+     * @param
+     *            boolean it could be that there is both a verbose and a
+     *            brief formatting available, and this argument controls that.
+     *
+     * @return string the number formatted as a string suitable for
+     *         display.
+     */
+    public function formatNumber($number, $brief = false)
+    {
+        return $number;
+    }
+
+    /**
+     * Get the numeric value of this entry as text.
+     *
+     * @param
+     *            boolean use brief output? The numbers will be separated
+     *            by a single space if brief output is requested, otherwise a space
+     *            and a comma will be used.
+     *
+     * @return string the numbers(s) held by this entry.
+     */
+    public function getText($brief = false)
+    {
+        if ($this->components == 0) {
+            return '';
+        }
+
+        $str = $this->formatNumber($this->value[0]);
+        for ($i = 1; $i < $this->components; $i ++) {
+            $str .= ($brief ? ' ' : ', ');
+            $str .= $this->formatNumber($this->value[$i]);
+        }
+
+        return $str;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryRational.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryRational.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff8c0611155a8acd271d318b919ed7da84d528c3
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryRational.php
@@ -0,0 +1,175 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to manipulate rational numbers.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding unsigned rational numbers.
+ *
+ * This class can hold rational numbers, consisting of a numerator and
+ * denominator both of which are of type unsigned long. Each rational
+ * is represented by an array with just two entries: the numerator and
+ * the denominator, in that order.
+ *
+ * The class can hold either just a single rational or an array of
+ * rationals. The class will be used to manipulate any of the Exif
+ * tags which can have format {@link PelFormat::RATIONAL} like in this
+ * example:
+ *
+ * <code>
+ * $resolution = $ifd->getEntry(PelTag::X_RESOLUTION);
+ * $resolution->setValue(array(1, 300));
+ * </code>
+ *
+ * Here the x-resolution is adjusted to 1/300, which will be 300 DPI,
+ * unless the {@link PelTag::RESOLUTION_UNIT resolution unit} is set
+ * to something different than 2 which means inches.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryRational extends PelEntryLong
+{
+
+    /**
+     * Make a new entry that can hold an unsigned rational.
+     *
+     * @param
+     *            PelTag the tag which this entry represents. This should
+     *            be one of the constants defined in {@link PelTag}, e.g., {@link
+     *            PelTag::X_RESOLUTION}, or any other tag which can have format
+     *            {@link PelFormat::RATIONAL}.
+     *
+     * @param array $value...
+     *            the rational(s) that this entry will
+     *            represent. The arguments passed must obey the same rules as the
+     *            argument to {@link setValue}, namely that each argument should be
+     *            an array with two entries, both of which must be within range of
+     *            an unsigned long (32 bit), that is between 0 and 4294967295
+     *            (inclusive). If not, then a {@link PelOverflowException} will be
+     *            thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->format = PelFormat::RATIONAL;
+        $this->dimension = 2;
+        $this->min = 0;
+        $this->max = 4294967295;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Format a rational number.
+     *
+     * The rational will be returned as a string with a slash '/'
+     * between the numerator and denominator.
+     *
+     * @param
+     *            array the rational which will be formatted.
+     *
+     * @param
+     *            boolean not used.
+     *
+     * @return string the rational formatted as a string suitable for
+     *         display.
+     */
+    public function formatNumber($number, $brief = false)
+    {
+        return $number[0] . '/' . $number[1];
+    }
+
+    /**
+     * Get the value of an entry as text.
+     *
+     * The value will be returned in a format suitable for presentation,
+     * e.g., rationals will be returned as 'x/y', ASCII strings will be
+     * returned as themselves etc.
+     *
+     * @param
+     *            boolean some values can be returned in a long or more
+     *            brief form, and this parameter controls that.
+     *
+     * @return string the value as text.
+     */
+    public function getText($brief = false)
+    {
+        if (isset($this->value[0])) {
+            $v = $this->value[0];
+        }
+
+        switch ($this->tag) {
+            case PelTag::FNUMBER:
+                // CC (e->components, 1, v);
+                return Pel::fmt('f/%.01f', $v[0] / $v[1]);
+
+            case PelTag::APERTURE_VALUE:
+                // CC (e->components, 1, v);
+                // if (!v_rat.denominator) return (NULL);
+                return Pel::fmt('f/%.01f', pow(2, $v[0] / $v[1] / 2));
+
+            case PelTag::FOCAL_LENGTH:
+                // CC (e->components, 1, v);
+                // if (!v_rat.denominator) return (NULL);
+                return Pel::fmt('%.1f mm', $v[0] / $v[1]);
+
+            case PelTag::SUBJECT_DISTANCE:
+                // CC (e->components, 1, v);
+                // if (!v_rat.denominator) return (NULL);
+                return Pel::fmt('%.1f m', $v[0] / $v[1]);
+
+            case PelTag::EXPOSURE_TIME:
+                // CC (e->components, 1, v);
+                // if (!v_rat.denominator) return (NULL);
+                if ($v[0] / $v[1] < 1) {
+                    return Pel::fmt('1/%d sec.', $v[1] / $v[0]);
+                } else {
+                    return Pel::fmt('%d sec.', $v[0] / $v[1]);
+                }
+                break;
+            case PelTag::GPS_LATITUDE:
+            case PelTag::GPS_LONGITUDE:
+                $degrees = $this->value[0][0] / $this->value[0][1];
+                $minutes = $this->value[1][0] / $this->value[1][1];
+                $seconds = $this->value[2][0] / $this->value[2][1];
+
+                return sprintf('%s° %s\' %s" (%.2f°)', $degrees, $minutes, $seconds, $degrees + $minutes / 60 + $seconds / 3600);
+
+            default:
+                return parent::getText($brief);
+        }
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySByte.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySByte.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5a992fb20c6f95d32c0868c8e38c48bd9c77416
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySByte.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold bytes, both signed and unsigned.
+ * The {@link
+ * PelEntryWindowsString} class is used to manipulate strings in the
+ * format Windows XP needs.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding signed bytes.
+ *
+ * This class can hold bytes, either just a single byte or an array of
+ * bytes. The class will be used to manipulate any of the Exif tags
+ * which has format {@link PelFormat::BYTE}.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntrySByte extends PelEntryNumber
+{
+
+    /**
+     * Make a new entry that can hold a signed byte.
+     *
+     * The method accept several integer arguments. The {@link getValue}
+     * method will always return an array except for when a single
+     * integer argument is given here.
+     *
+     * @param PelTag $tag
+     *            the tag which this entry represents. This
+     *            should be one of the constants defined in {@link PelTag}
+     *            which has format {@link PelFormat::BYTE}.
+     *
+     * @param int $value...
+     *            the byte(s) that this entry will represent.
+     *            The argument passed must obey the same rules as the argument to
+     *            {@link setValue}, namely that it should be within range of a
+     *            signed byte, that is between -128 and 127 (inclusive). If not,
+     *            then a {@link PelOverflowException} will be thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->min = - 128;
+        $this->max = 127;
+        $this->format = PelFormat::SBYTE;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Convert a number into bytes.
+     *
+     * @param int $number
+     *            the number that should be converted.
+     *
+     * @param PelByteOrder $order
+     *            one of {@link PelConvert::LITTLE_ENDIAN} and
+     *            {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
+     *
+     * @return string bytes representing the number given.
+     */
+    public function numberToBytes($number, $order)
+    {
+        return chr($number);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySLong.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySLong.php
new file mode 100644
index 0000000000000000000000000000000000000000..c596a48f96507a77c4e359706291d77d9e34be48
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySLong.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold longs, both signed and unsigned.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding signed longs.
+ *
+ * This class can hold longs, either just a single long or an array of
+ * longs. The class will be used to manipulate any of the Exif tags
+ * which can have format {@link PelFormat::SLONG}.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntrySLong extends PelEntryNumber
+{
+
+    /**
+     * Make a new entry that can hold a signed long.
+     *
+     * The method accept its arguments in two forms: several integer
+     * arguments or a single array argument. The {@link getValue}
+     * method will always return an array except for when a single
+     * integer argument is given here, or when an array with just a
+     * single integer is given.
+     *
+     * @param
+     *            PelTag the tag which this entry represents. This
+     *            should be one of the constants defined in {@link PelTag}
+     *            which have format {@link PelFormat::SLONG}.
+     *
+     * @param int $value...
+     *            the long(s) that this entry will represent
+     *            or an array of longs. The argument passed must obey the same
+     *            rules as the argument to {@link setValue}, namely that it should
+     *            be within range of a signed long (32 bit), that is between
+     *            -2147483648 and 2147483647 (inclusive). If not, then a {@link
+     *            PelOverflowException} will be thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->min = - 2147483648;
+        $this->max = 2147483647;
+        $this->format = PelFormat::SLONG;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Convert a number into bytes.
+     *
+     * @param
+     *            int the number that should be converted.
+     *
+     * @param
+     *            PelByteOrder one of {@link PelConvert::LITTLE_ENDIAN} and
+     *            {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
+     *
+     * @return string bytes representing the number given.
+     */
+    public function numberToBytes($number, $order)
+    {
+        return PelConvert::sLongToBytes($number, $order);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySRational.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySRational.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4dcb8d6974d842fbb59acd35595c30850e39303
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySRational.php
@@ -0,0 +1,153 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to manipulate rational numbers.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding signed rational numbers.
+ *
+ * This class can hold rational numbers, consisting of a numerator and
+ * denominator both of which are of type unsigned long. Each rational
+ * is represented by an array with just two entries: the numerator and
+ * the denominator, in that order.
+ *
+ * The class can hold either just a single rational or an array of
+ * rationals. The class will be used to manipulate any of the Exif
+ * tags which can have format {@link PelFormat::SRATIONAL}.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntrySRational extends PelEntrySLong
+{
+
+    /**
+     * Make a new entry that can hold a signed rational.
+     *
+     * @param
+     *            PelTag the tag which this entry represents. This should
+     *            be one of the constants defined in {@link PelTag}, e.g., {@link
+     *            PelTag::SHUTTER_SPEED_VALUE}, or any other tag which can have
+     *            format {@link PelFormat::SRATIONAL}.
+     *
+     * @param array $value...
+     *            the rational(s) that this entry will
+     *            represent. The arguments passed must obey the same rules as the
+     *            argument to {@link setValue}, namely that each argument should be
+     *            an array with two entries, both of which must be within range of
+     *            a signed long (32 bit), that is between -2147483648 and
+     *            2147483647 (inclusive). If not, then a {@link
+     *            PelOverflowException} will be thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->format = PelFormat::SRATIONAL;
+        $this->dimension = 2;
+        $this->min = - 2147483648;
+        $this->max = 2147483647;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Format a rational number.
+     *
+     * The rational will be returned as a string with a slash '/'
+     * between the numerator and denominator. Care is taken to display
+     * '-1/2' instead of the ugly but mathematically equivalent '1/-2'.
+     *
+     * @param
+     *            array the rational which will be formatted.
+     *
+     * @param
+     *            boolean not used.
+     *
+     * @return string the rational formatted as a string suitable for
+     *         display.
+     */
+    public function formatNumber($number, $brief = false)
+    {
+        if ($number[1] < 0) {
+            /* Turn output like 1/-2 into -1/2. */
+            return (- $number[0]) . '/' . (- $number[1]);
+        } else {
+            return $number[0] . '/' . $number[1];
+        }
+    }
+
+    /**
+     * Get the value of an entry as text.
+     *
+     * The value will be returned in a format suitable for presentation,
+     * e.g., rationals will be returned as 'x/y', ASCII strings will be
+     * returned as themselves etc.
+     *
+     * @param
+     *            boolean some values can be returned in a long or more
+     *            brief form, and this parameter controls that.
+     *
+     * @return string the value as text.
+     */
+    public function getText($brief = false)
+    {
+        if (isset($this->value[0])) {
+            $v = $this->value[0];
+        }
+
+        switch ($this->tag) {
+            case PelTag::SHUTTER_SPEED_VALUE:
+                // CC (e->components, 1, v);
+                // if (!v_srat.denominator) return (NULL);
+                return Pel::fmt('%.0f/%.0f sec. (APEX: %d)', $v[0], $v[1], pow(sqrt(2), $v[0] / $v[1]));
+
+            case PelTag::BRIGHTNESS_VALUE:
+                // CC (e->components, 1, v);
+                //
+                // TODO: figure out the APEX thing, or remove this so that it is
+                // handled by the default clause at the bottom.
+                return sprintf('%d/%d', $v[0], $v[1]);
+            // FIXME: How do I calculate the APEX value?
+
+            case PelTag::EXPOSURE_BIAS_VALUE:
+                // CC (e->components, 1, v);
+                // if (!v_srat.denominator) return (NULL);
+                return sprintf('%s%.01f', $v[0] * $v[1] > 0 ? '+' : '', $v[0] / $v[1]);
+
+            default:
+                return parent::getText($brief);
+        }
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySShort.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySShort.php
new file mode 100644
index 0000000000000000000000000000000000000000..886b530e53103d74c9a0efe0dcb37b81cefba844
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntrySShort.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold shorts, both signed and unsigned.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding signed shorts.
+ *
+ * This class can hold shorts, either just a single short or an array
+ * of shorts. The class will be used to manipulate any of the Exif
+ * tags which has format {@link PelFormat::SSHORT}.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntrySShort extends PelEntryNumber
+{
+
+    /**
+     * Make a new entry that can hold a signed short.
+     *
+     * The method accept several integer arguments. The {@link
+     * getValue} method will always return an array except for when a
+     * single integer argument is given here.
+     *
+     * @param PelTag $tag
+     *            the tag which this entry represents. This
+     *            should be one of the constants defined in {@link PelTag}
+     *            which has format {@link PelFormat::SSHORT}.
+     *
+     * @param int $value...
+     *            the signed short(s) that this entry will
+     *            represent. The argument passed must obey the same rules as the
+     *            argument to {@link setValue}, namely that it should be within
+     *            range of a signed short, that is between -32768 to 32767
+     *            (inclusive). If not, then a {@link PelOverFlowException} will be
+     *            thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->min = - 32768;
+        $this->max = 32767;
+        $this->format = PelFormat::SSHORT;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Convert a number into bytes.
+     *
+     * @param int $number
+     *            the number that should be converted.
+     *
+     * @param PelByteOrder $order
+     *            one of {@link PelConvert::LITTLE_ENDIAN} and
+     *            {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
+     *
+     * @return string bytes representing the number given.
+     */
+    public function numberToBytes($number, $order)
+    {
+        return PelConvert::sShortToBytes($number, $order);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryShort.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryShort.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ef5cffc7a566f5a184cd4f49f1e132baec99c29
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryShort.php
@@ -0,0 +1,534 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold shorts, both signed and unsigned.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding signed shorts.
+ *
+ * This class can hold shorts, either just a single short or an array
+ * of shorts. The class will be used to manipulate any of the Exif
+ * tags which has format {@link PelFormat::SHORT} like in this
+ * example:
+ *
+ * <code>
+ * $w = $ifd->getEntry(PelTag::EXIF_IMAGE_WIDTH);
+ * $w->setValue($w->getValue() / 2);
+ * $h = $ifd->getEntry(PelTag::EXIF_IMAGE_HEIGHT);
+ * $h->setValue($h->getValue() / 2);
+ * </code>
+ *
+ * Here the width and height is updated to 50% of their original
+ * values.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryShort extends PelEntryNumber
+{
+
+    /**
+     * Make a new entry that can hold an unsigned short.
+     *
+     * The method accept several integer arguments. The {@link
+     * getValue} method will always return an array except for when a
+     * single integer argument is given here.
+     *
+     * This means that one can conveniently use objects like this:
+     * <code>
+     * $a = new PelEntryShort(PelTag::EXIF_IMAGE_HEIGHT, 42);
+     * $b = $a->getValue() + 314;
+     * </code>
+     * where the call to {@link getValue} will return an integer
+     * instead of an array with one integer element, which would then
+     * have to be extracted.
+     *
+     * @param PelTag $tag
+     *            the tag which this entry represents. This should be
+     *            one of the constants defined in {@link PelTag}, e.g., {@link
+     *            PelTag::IMAGE_WIDTH}, {@link PelTag::ISO_SPEED_RATINGS},
+     *            or any other tag with format {@link PelFormat::SHORT}.
+     *
+     * @param int $value...
+     *            the short(s) that this entry will
+     *            represent. The argument passed must obey the same rules as the
+     *            argument to {@link setValue}, namely that it should be within
+     *            range of an unsigned short, that is between 0 and 65535
+     *            (inclusive). If not, then a {@link PelOverFlowException} will be
+     *            thrown.
+     */
+    public function __construct($tag, $value = null)
+    {
+        $this->tag = $tag;
+        $this->min = 0;
+        $this->max = 65535;
+        $this->format = PelFormat::SHORT;
+
+        $value = func_get_args();
+        array_shift($value);
+        $this->setValueArray($value);
+    }
+
+    /**
+     * Convert a number into bytes.
+     *
+     * @param int $number
+     *            the number that should be converted.
+     *
+     * @param PelByteOrder $order
+     *            one of {@link PelConvert::LITTLE_ENDIAN} and
+     *            {@link PelConvert::BIG_ENDIAN}, specifying the target byte order.
+     *
+     * @return string bytes representing the number given.
+     */
+    public function numberToBytes($number, $order)
+    {
+        return PelConvert::shortToBytes($number, $order);
+    }
+
+    /**
+     * Get the value of an entry as text.
+     *
+     * The value will be returned in a format suitable for presentation,
+     * e.g., instead of returning '2' for a {@link
+     * PelTag::METERING_MODE} tag, 'Center-Weighted Average' is
+     * returned.
+     *
+     * @param
+     *            boolean some values can be returned in a long or more
+     *            brief form, and this parameter controls that.
+     *
+     * @return string the value as text.
+     */
+    public function getText($brief = false)
+    {
+        switch ($this->tag) {
+            case PelTag::METERING_MODE:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Unknown');
+                    case 1:
+                        return Pel::tra('Average');
+                    case 2:
+                        return Pel::tra('Center-Weighted Average');
+                    case 3:
+                        return Pel::tra('Spot');
+                    case 4:
+                        return Pel::tra('Multi Spot');
+                    case 5:
+                        return Pel::tra('Pattern');
+                    case 6:
+                        return Pel::tra('Partial');
+                    case 255:
+                        return Pel::tra('Other');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::COMPRESSION:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 1:
+                        return Pel::tra('Uncompressed');
+                    case 6:
+                        return Pel::tra('JPEG compression');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::PLANAR_CONFIGURATION:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 1:
+                        return Pel::tra('chunky format');
+                    case 2:
+                        return Pel::tra('planar format');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::SENSING_METHOD:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 1:
+                        return Pel::tra('Not defined');
+                    case 2:
+                        return Pel::tra('One-chip color area sensor');
+                    case 3:
+                        return Pel::tra('Two-chip color area sensor');
+                    case 4:
+                        return Pel::tra('Three-chip color area sensor');
+                    case 5:
+                        return Pel::tra('Color sequential area sensor');
+                    case 7:
+                        return Pel::tra('Trilinear sensor');
+                    case 8:
+                        return Pel::tra('Color sequential linear sensor');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::LIGHT_SOURCE:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Unknown');
+                    case 1:
+                        return Pel::tra('Daylight');
+                    case 2:
+                        return Pel::tra('Fluorescent');
+                    case 3:
+                        return Pel::tra('Tungsten (incandescent light)');
+                    case 4:
+                        return Pel::tra('Flash');
+                    case 9:
+                        return Pel::tra('Fine weather');
+                    case 10:
+                        return Pel::tra('Cloudy weather');
+                    case 11:
+                        return Pel::tra('Shade');
+                    case 12:
+                        return Pel::tra('Daylight fluorescent');
+                    case 13:
+                        return Pel::tra('Day white fluorescent');
+                    case 14:
+                        return Pel::tra('Cool white fluorescent');
+                    case 15:
+                        return Pel::tra('White fluorescent');
+                    case 17:
+                        return Pel::tra('Standard light A');
+                    case 18:
+                        return Pel::tra('Standard light B');
+                    case 19:
+                        return Pel::tra('Standard light C');
+                    case 20:
+                        return Pel::tra('D55');
+                    case 21:
+                        return Pel::tra('D65');
+                    case 22:
+                        return Pel::tra('D75');
+                    case 24:
+                        return Pel::tra('ISO studio tungsten');
+                    case 255:
+                        return Pel::tra('Other');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::FOCAL_PLANE_RESOLUTION_UNIT:
+            case PelTag::RESOLUTION_UNIT:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 2:
+                        return Pel::tra('Inch');
+                    case 3:
+                        return Pel::tra('Centimeter');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::EXPOSURE_PROGRAM:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Not defined');
+                    case 1:
+                        return Pel::tra('Manual');
+                    case 2:
+                        return Pel::tra('Normal program');
+                    case 3:
+                        return Pel::tra('Aperture priority');
+                    case 4:
+                        return Pel::tra('Shutter priority');
+                    case 5:
+                        return Pel::tra('Creative program (biased toward depth of field)');
+                    case 6:
+                        return Pel::tra('Action program (biased toward fast shutter speed)');
+                    case 7:
+                        return Pel::tra('Portrait mode (for closeup photos with the background out of focus');
+                    case 8:
+                        return Pel::tra('Landscape mode (for landscape photos with the background in focus');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::ORIENTATION:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 1:
+                        return Pel::tra('top - left');
+                    case 2:
+                        return Pel::tra('top - right');
+                    case 3:
+                        return Pel::tra('bottom - right');
+                    case 4:
+                        return Pel::tra('bottom - left');
+                    case 5:
+                        return Pel::tra('left - top');
+                    case 6:
+                        return Pel::tra('right - top');
+                    case 7:
+                        return Pel::tra('right - bottom');
+                    case 8:
+                        return Pel::tra('left - bottom');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::YCBCR_POSITIONING:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 1:
+                        return Pel::tra('centered');
+                    case 2:
+                        return Pel::tra('co-sited');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::YCBCR_SUB_SAMPLING:
+                // CC (e->components, 2, v);
+                if ($this->value[0] == 2 && $this->value[1] == 1) {
+                    return 'YCbCr4:2:2';
+                }
+                if ($this->value[0] == 2 && $this->value[1] == 2) {
+                    return 'YCbCr4:2:0';
+                }
+
+                return $this->value[0] . ', ' . $this->value[1];
+                break;
+            case PelTag::PHOTOMETRIC_INTERPRETATION:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 2:
+                        return 'RGB';
+                    case 6:
+                        return 'YCbCr';
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::COLOR_SPACE:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 1:
+                        return 'sRGB';
+                    case 2:
+                        return 'Adobe RGB';
+                    case 0xffff:
+                        return Pel::tra('Uncalibrated');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::FLASH:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0x0000:
+                        return Pel::tra('Flash did not fire.');
+                    case 0x0001:
+                        return Pel::tra('Flash fired.');
+                    case 0x0005:
+                        return Pel::tra('Strobe return light not detected.');
+                    case 0x0007:
+                        return Pel::tra('Strobe return light detected.');
+                    case 0x0009:
+                        return Pel::tra('Flash fired, compulsory flash mode.');
+                    case 0x000d:
+                        return Pel::tra('Flash fired, compulsory flash mode, return light not detected.');
+                    case 0x000f:
+                        return Pel::tra('Flash fired, compulsory flash mode, return light detected.');
+                    case 0x0010:
+                        return Pel::tra('Flash did not fire, compulsory flash mode.');
+                    case 0x0018:
+                        return Pel::tra('Flash did not fire, auto mode.');
+                    case 0x0019:
+                        return Pel::tra('Flash fired, auto mode.');
+                    case 0x001d:
+                        return Pel::tra('Flash fired, auto mode, return light not detected.');
+                    case 0x001f:
+                        return Pel::tra('Flash fired, auto mode, return light detected.');
+                    case 0x0020:
+                        return Pel::tra('No flash function.');
+                    case 0x0041:
+                        return Pel::tra('Flash fired, red-eye reduction mode.');
+                    case 0x0045:
+                        return Pel::tra('Flash fired, red-eye reduction mode, return light not detected.');
+                    case 0x0047:
+                        return Pel::tra('Flash fired, red-eye reduction mode, return light detected.');
+                    case 0x0049:
+                        return Pel::tra('Flash fired, compulsory flash mode, red-eye reduction mode.');
+                    case 0x004d:
+                        return Pel::tra('Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected.');
+                    case 0x004f:
+                        return Pel::tra('Flash fired, compulsory flash mode, red-eye reduction mode, return light detected.');
+                    case 0x0058:
+                        return Pel::tra('Flash did not fire, auto mode, red-eye reduction mode.');
+                    case 0x0059:
+                        return Pel::tra('Flash fired, auto mode, red-eye reduction mode.');
+                    case 0x005d:
+                        return Pel::tra('Flash fired, auto mode, return light not detected, red-eye reduction mode.');
+                    case 0x005f:
+                        return Pel::tra('Flash fired, auto mode, return light detected, red-eye reduction mode.');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::CUSTOM_RENDERED:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Normal process');
+                    case 1:
+                        return Pel::tra('Custom process');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::EXPOSURE_MODE:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Auto exposure');
+                    case 1:
+                        return Pel::tra('Manual exposure');
+                    case 2:
+                        return Pel::tra('Auto bracket');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::WHITE_BALANCE:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Auto white balance');
+                    case 1:
+                        return Pel::tra('Manual white balance');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::SCENE_CAPTURE_TYPE:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Standard');
+                    case 1:
+                        return Pel::tra('Landscape');
+                    case 2:
+                        return Pel::tra('Portrait');
+                    case 3:
+                        return Pel::tra('Night scene');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::GAIN_CONTROL:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Normal');
+                    case 1:
+                        return Pel::tra('Low gain up');
+                    case 2:
+                        return Pel::tra('High gain up');
+                    case 3:
+                        return Pel::tra('Low gain down');
+                    case 4:
+                        return Pel::tra('High gain down');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::SATURATION:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Normal');
+                    case 1:
+                        return Pel::tra('Low saturation');
+                    case 2:
+                        return Pel::tra('High saturation');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::CONTRAST:
+            case PelTag::SHARPNESS:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Normal');
+                    case 1:
+                        return Pel::tra('Soft');
+                    case 2:
+                        return Pel::tra('Hard');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::SUBJECT_DISTANCE_RANGE:
+                // CC (e->components, 1, v);
+                switch ($this->value[0]) {
+                    case 0:
+                        return Pel::tra('Unknown');
+                    case 1:
+                        return Pel::tra('Macro');
+                    case 2:
+                        return Pel::tra('Close view');
+                    case 3:
+                        return Pel::tra('Distant view');
+                    default:
+                        return $this->value[0];
+                }
+                break;
+            case PelTag::SUBJECT_AREA:
+                switch ($this->components) {
+                    case 2:
+                        return Pel::fmt('(x,y) = (%d,%d)', $this->value[0], $this->value[1]);
+                    case 3:
+                        return Pel::fmt('Within distance %d of (x,y) = (%d,%d)', $this->value[0], $this->value[1], $this->value[2]);
+                    case 4:
+                        return Pel::fmt('Within rectangle (width %d, height %d) around (x,y) = (%d,%d)', $this->value[0], $this->value[1], $this->value[2], $this->value[3]);
+
+                    default:
+                        return Pel::fmt('Unexpected number of components (%d, expected 2, 3, or 4).', $this->components);
+                }
+                break;
+            default:
+                return parent::getText($brief);
+        }
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryTime.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryTime.php
new file mode 100644
index 0000000000000000000000000000000000000000..da64eaaaaebffe40c10a0f71e556262167a099cd
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryTime.php
@@ -0,0 +1,352 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold ASCII strings.
+ *
+ * The classes defined here are to be used for Exif entries holding
+ * ASCII strings, such as {@link PelTag::MAKE}, {@link
+ * PelTag::SOFTWARE}, and {@link PelTag::DATE_TIME}. For
+ * entries holding normal textual ASCII strings the class {@link
+ * PelEntryAscii} should be used, but for entries holding
+ * timestamps the class {@link PelEntryTime} would be more
+ * convenient instead. Copyright information is handled by the {@link
+ * PelEntryCopyright} class.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding a date and time.
+ *
+ * This class can hold a timestamp, and it will be used as
+ * in this example where the time is advanced by one week:
+ * <code>
+ * $entry = $ifd->getEntry(PelTag::DATE_TIME_ORIGINAL);
+ * $time = $entry->getValue();
+ * print('The image was taken on the ' . date('jS', $time));
+ * $entry->setValue($time + 7 * 24 * 3600);
+ * </code>
+ *
+ * The example used a standard UNIX timestamp, which is the default
+ * for this class.
+ *
+ * But the Exif format defines dates outside the range of a UNIX
+ * timestamp (about 1970 to 2038) and so you can also get access to
+ * the timestamp in two other formats: a simple string or a Julian Day
+ * Count. Please see the Calendar extension in the PHP Manual for more
+ * information about the Julian Day Count.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryTime extends PelEntryAscii
+{
+
+    /**
+     * Constant denoting a UNIX timestamp.
+     */
+    const UNIX_TIMESTAMP = 1;
+
+    /**
+     * Constant denoting a Exif string.
+     */
+    const EXIF_STRING = 2;
+
+    /**
+     * Constant denoting a Julian Day Count.
+     */
+    const JULIAN_DAY_COUNT = 3;
+
+    /**
+     * The Julian Day Count of the timestamp held by this entry.
+     *
+     * This is an integer counting the number of whole days since
+     * January 1st, 4713 B.C. The fractional part of the timestamp held
+     * by this entry is stored in {@link $seconds}.
+     *
+     * @var int
+     */
+    private $day_count;
+
+    /**
+     * The number of seconds into the day of the timestamp held by this
+     * entry.
+     *
+     * The number of whole days is stored in {@link $day_count} and the
+     * number of seconds left-over is stored here.
+     *
+     * @var int
+     */
+    private $seconds;
+
+    /**
+     * Make a new entry for holding a timestamp.
+     *
+     * @param integer $tag
+     *            the Exif tag which this entry represents. There are
+     *            only three standard tags which hold timestamp, so this should be
+     *            one of the constants {@link PelTag::DATE_TIME}, {@link
+     *            PelTag::DATE_TIME_ORIGINAL}, or {@link
+     *            PelTag::DATE_TIME_DIGITIZED}.
+     *
+     * @param integer $timestamp
+     *            the timestamp held by this entry in the correct form
+     *            as indicated by the third argument. For {@link UNIX_TIMESTAMP}
+     *            this is an integer counting the number of seconds since January
+     *            1st 1970, for {@link EXIF_STRING} this is a string of the form
+     *            'YYYY:MM:DD hh:mm:ss', and for {@link JULIAN_DAY_COUNT} this is a
+     *            floating point number where the integer part denotes the day
+     *            count and the fractional part denotes the time of day (0.25 means
+     *            6:00, 0.75 means 18:00).
+     *
+     * @param integer $type
+     *            the type of the timestamp. This must be one of
+     *            {@link UNIX_TIMESTAMP}, {@link EXIF_STRING}, or
+     *            {@link JULIAN_DAY_COUNT}.
+     */
+    public function __construct($tag, $timestamp, $type = self::UNIX_TIMESTAMP)
+    {
+        parent::__construct($tag);
+        $this->setValue($timestamp, $type);
+    }
+
+    /**
+     * Return the timestamp of the entry.
+     *
+     * The timestamp held by this entry is returned in one of three
+     * formats: as a standard UNIX timestamp (default), as a fractional
+     * Julian Day Count, or as a string.
+     *
+     * @param integer $type
+     *            the type of the timestamp. This must be one of
+     *            {@link UNIX_TIMESTAMP}, {@link EXIF_STRING}, or
+     *            {@link JULIAN_DAY_COUNT}.
+     *
+     * @return integer the timestamp held by this entry in the correct form
+     *         as indicated by the type argument. For {@link UNIX_TIMESTAMP}
+     *         this is an integer counting the number of seconds since January
+     *         1st 1970, for {@link EXIF_STRING} this is a string of the form
+     *         'YYYY:MM:DD hh:mm:ss', and for {@link JULIAN_DAY_COUNT} this is a
+     *         floating point number where the integer part denotes the day
+     *         count and the fractional part denotes the time of day (0.25 means
+     *         6:00, 0.75 means 18:00).
+     */
+    public function getValue($type = self::UNIX_TIMESTAMP)
+    {
+        switch ($type) {
+            case self::UNIX_TIMESTAMP:
+                $seconds = $this->convertJdToUnix($this->day_count);
+                if ($seconds === false) {
+                    /*
+                     * We get false if the Julian Day Count is outside the range
+                     * of a UNIX timestamp.
+                     */
+                    return false;
+                } else {
+                    return $seconds + $this->seconds;
+                }
+                break;
+            case self::EXIF_STRING:
+                list ($year, $month, $day) = $this->convertJdToGregorian($this->day_count);
+                $hours = (int) ($this->seconds / 3600);
+                $minutes = (int) ($this->seconds % 3600 / 60);
+                $seconds = $this->seconds % 60;
+                return sprintf('%04d:%02d:%02d %02d:%02d:%02d', $year, $month, $day, $hours, $minutes, $seconds);
+            case self::JULIAN_DAY_COUNT:
+                return $this->day_count + $this->seconds / 86400;
+            default:
+                throw new PelInvalidArgumentException(
+                    'Expected UNIX_TIMESTAMP (%d), ' . 'EXIF_STRING (%d), or ' . 'JULIAN_DAY_COUNT (%d) for $type, ' .
+                         'got %d.',
+                        self::UNIX_TIMESTAMP,
+                        self::EXIF_STRING,
+                        self::JULIAN_DAY_COUNT,
+                        $type);
+        }
+    }
+
+    /**
+     * Update the timestamp held by this entry.
+     *
+     * @param integer $timestamp
+     *            the timestamp held by this entry in the correct form
+     *            as indicated by the third argument. For {@link UNIX_TIMESTAMP}
+     *            this is an integer counting the number of seconds since January
+     *            1st 1970, for {@link EXIF_STRING} this is a string of the form
+     *            'YYYY:MM:DD hh:mm:ss', and for {@link JULIAN_DAY_COUNT} this is a
+     *            floating point number where the integer part denotes the day
+     *            count and the fractional part denotes the time of day (0.25 means
+     *            6:00, 0.75 means 18:00).
+     *
+     * @param integer $type
+     *            the type of the timestamp. This must be one of
+     *            {@link UNIX_TIMESTAMP}, {@link EXIF_STRING}, or
+     *            {@link JULIAN_DAY_COUNT}.
+     */
+    public function setValue($timestamp, $type = self::UNIX_TIMESTAMP)
+    {
+        switch ($type) {
+            case self::UNIX_TIMESTAMP:
+                $this->day_count = $this->convertUnixToJd($timestamp);
+                $this->seconds = $timestamp % 86400;
+                break;
+
+            case self::EXIF_STRING:
+                /* Clean the timestamp: some timestamps are broken other
+                 * separators than ':' and ' '. */
+                $d = preg_split('/[^0-9]+/', $timestamp);
+                for ($i = 0; $i < 6; $i ++) {
+                    if (empty($d[$i])) {
+                        $d[$i] = 0;
+                    }
+                }
+                $this->day_count = $this->convertGregorianToJd($d[0], $d[1], $d[2]);
+                $this->seconds = $d[3] * 3600 + $d[4] * 60 + $d[5];
+                break;
+
+            case self::JULIAN_DAY_COUNT:
+                $this->day_count = (int) floor($timestamp);
+                $this->seconds = (int) (86400 * ($timestamp - floor($timestamp)));
+                break;
+
+            default:
+                throw new PelInvalidArgumentException(
+                    'Expected UNIX_TIMESTAMP (%d), ' . 'EXIF_STRING (%d), or ' . 'JULIAN_DAY_COUNT (%d) for $type, ' .
+                         'got %d.',
+                        self::UNIX_TIMESTAMP,
+                        self::EXIF_STRING,
+                        self::JULIAN_DAY_COUNT,
+                        $type);
+        }
+
+        /*
+         * Now finally update the string which will be used when this is
+         * turned into bytes.
+         */
+        parent::setValue($this->getValue(self::EXIF_STRING));
+    }
+
+    // The following four functions are used for converting back and
+    // forth between the date formats. They are used in preference to
+    // the ones from the PHP calendar extension to avoid having to
+    // fiddle with timezones and to avoid depending on the extension.
+    //
+    // See http://www.hermetic.ch/cal_stud/jdn.htm#comp for a reference.
+
+    /**
+     * Converts a date in year/month/day format to a Julian Day count.
+     *
+     * @param integer $year
+     *            the year.
+     * @param integer $month
+     *            the month, 1 to 12.
+     * @param integer $day
+     *            the day in the month.
+     * @return integer the Julian Day count.
+     */
+    public function convertGregorianToJd($year, $month, $day)
+    {
+        // Special case mapping 0/0/0 -> 0
+        if ($year == 0 || $month == 0 || $day == 0) {
+            return 0;
+        }
+
+        $m1412 = ($month <= 2) ? - 1 : 0;
+        return floor((1461 * ($year + 4800 + $m1412)) / 4) + floor((367 * ($month - 2 - 12 * $m1412)) / 12) -
+             floor((3 * floor(($year + 4900 + $m1412) / 100)) / 4) + $day - 32075;
+    }
+
+    /**
+     * Converts a Julian Day count to a year/month/day triple.
+     *
+     * @param
+     *            int the Julian Day count.
+     * @return array an array with three entries: year, month, day.
+     */
+    public function convertJdToGregorian($jd)
+    {
+        // Special case mapping 0 -> 0/0/0
+        if ($jd == 0) {
+            return array(
+                0,
+                0,
+                0
+            );
+        }
+
+        $l = $jd + 68569;
+        $n = floor((4 * $l) / 146097);
+        $l = $l - floor((146097 * $n + 3) / 4);
+        $i = floor((4000 * ($l + 1)) / 1461001);
+        $l = $l - floor((1461 * $i) / 4) + 31;
+        $j = floor((80 * $l) / 2447);
+        $d = $l - floor((2447 * $j) / 80);
+        $l = floor($j / 11);
+        $m = $j + 2 - (12 * $l);
+        $y = 100 * ($n - 49) + $i + $l;
+        return array(
+            $y,
+            $m,
+            $d
+        );
+    }
+
+    /**
+     * Converts a UNIX timestamp to a Julian Day count.
+     *
+     * @param integer $timestamp
+     *            the timestamp.
+     * @return integer the Julian Day count.
+     */
+    public function convertUnixToJd($timestamp)
+    {
+        return (int) (floor($timestamp / 86400) + 2440588);
+    }
+
+    /**
+     * Converts a Julian Day count to a UNIX timestamp.
+     *
+     * @param integer $jd
+     *            the Julian Day count.
+     *
+     * @return mixed $timestamp the integer timestamp or false if the
+     *         day count cannot be represented as a UNIX timestamp.
+     */
+    public function convertJdToUnix($jd)
+    {
+        if ($jd > 0) {
+            $timestamp = ($jd - 2440588) * 86400;
+            if ($timestamp >= 0) {
+                return $timestamp;
+            }
+        }
+        return false;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryUndefined.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryUndefined.php
new file mode 100644
index 0000000000000000000000000000000000000000..a2112c370f00e4dd545320e02f192e91a1651b3c
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryUndefined.php
@@ -0,0 +1,173 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold data for Exif tags of format undefined.
+ *
+ * This file contains the base class {@link PelEntryUndefined} and
+ * the subclasses {@link PelEntryUserComment} which should be used
+ * to manage the {@link PelTag::USER_COMMENT} tag, and {@link
+ * PelEntryVersion} which is used to manage entries with version
+ * information.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for holding data of any kind.
+ *
+ * This class can hold bytes of undefined format.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryUndefined extends PelEntry
+{
+
+    /**
+     * Make a new PelEntry that can hold undefined data.
+     *
+     * @param integer $tag
+     *            which this entry represents. This
+     *            should be one of the constants defined in {@link PelTag},
+     *            e.g., {@link PelTag::SCENE_TYPE}, {@link
+     *            PelTag::MAKER_NOTE} or any other tag with format {@link
+     *            PelFormat::UNDEFINED}.
+     *
+     * @param string $data
+     *            the data that this entry will be holding. Since
+     *            the format is undefined, no checking will be done on the data. If no data are given, a empty string will be stored
+     */
+    public function __construct($tag, $data = '')
+    {
+        $this->tag = $tag;
+        $this->format = PelFormat::UNDEFINED;
+        $this->setValue($data);
+    }
+
+    /**
+     * Set the data of this undefined entry.
+     *
+     * @param string $data
+     *            the data that this entry will be holding. Since
+     *            the format is undefined, no checking will be done on the data.
+     */
+    public function setValue($data)
+    {
+        $this->components = strlen($data);
+        $this->bytes = $data;
+    }
+
+    /**
+     * Get the data of this undefined entry.
+     *
+     * @return string the data that this entry is holding.
+     */
+    public function getValue()
+    {
+        return $this->bytes;
+    }
+
+    /**
+     * Get the value of this entry as text.
+     *
+     * The value will be returned in a format suitable for presentation.
+     *
+     * @param
+     *            boolean some values can be returned in a long or more
+     *            brief form, and this parameter controls that.
+     *
+     * @return string the value as text.
+     */
+    public function getText($brief = false)
+    {
+        switch ($this->tag) {
+            case PelTag::FILE_SOURCE:
+                // CC (e->components, 1, v);
+                switch (ord($this->bytes{0})) {
+                    case 0x03:
+                        return 'DSC';
+                    default:
+                        return sprintf('0x%02X', ord($this->bytes{0}));
+                }
+                break;
+            case PelTag::SCENE_TYPE:
+                // CC (e->components, 1, v);
+                switch (ord($this->bytes{0})) {
+                    case 0x01:
+                        return 'Directly photographed';
+                    default:
+                        return sprintf('0x%02X', ord($this->bytes{0}));
+                }
+                break;
+            case PelTag::COMPONENTS_CONFIGURATION:
+                // CC (e->components, 4, v);
+                $v = '';
+                for ($i = 0; $i < 4; $i ++) {
+                    switch (ord($this->bytes{$i})) {
+                        case 0:
+                            $v .= '-';
+                            break;
+                        case 1:
+                            $v .= 'Y';
+                            break;
+                        case 2:
+                            $v .= 'Cb';
+                            break;
+                        case 3:
+                            $v .= 'Cr';
+                            break;
+                        case 4:
+                            $v .= 'R';
+                            break;
+                        case 5:
+                            $v .= 'G';
+                            break;
+                        case 6:
+                            $v .= 'B';
+                            break;
+                        default:
+                            $v .= 'reserved';
+                            break;
+                    }
+                    if ($i < 3) {
+                        $v .= ' ';
+                    }
+                }
+                return $v;
+                break;
+            case PelTag::MAKER_NOTE:
+                // TODO: handle maker notes.
+                return $this->components . ' bytes unknown MakerNote data';
+                break;
+            default:
+                return '(undefined)';
+        }
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryUserComment.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryUserComment.php
new file mode 100644
index 0000000000000000000000000000000000000000..20dc8bc3968111c538d9760507f0fb72610d7e07
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryUserComment.php
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold data for Exif tags of format undefined.
+ *
+ * This file contains the base class {@link PelEntryUndefined} and
+ * the subclasses {@link PelEntryUserComment} which should be used
+ * to manage the {@link PelTag::USER_COMMENT} tag, and {@link
+ * PelEntryVersion} which is used to manage entries with version
+ * information.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for a user comment.
+ *
+ * This class is used to hold user comments, which can come in several
+ * different character encodings. The Exif standard specifies a
+ * certain format of the {@link PelTag::USER_COMMENT user comment
+ * tag}, and this class will make sure that the format is kept.
+ *
+ * The most basic use of this class simply stores an ASCII encoded
+ * string for later retrieval using {@link getValue}:
+ *
+ * <code>
+ * $entry = new PelEntryUserComment('An ASCII string');
+ * echo $entry->getValue();
+ * </code>
+ *
+ * The string can be encoded with a different encoding, and if so, the
+ * encoding must be given using the second argument. The Exif
+ * standard specifies three known encodings: 'ASCII', 'JIS', and
+ * 'Unicode'. If the user comment is encoded using a character
+ * encoding different from the tree known encodings, then the empty
+ * string should be passed as encoding, thereby specifying that the
+ * encoding is undefined.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryUserComment extends PelEntryUndefined
+{
+
+    /**
+     * The user comment.
+     *
+     * @var string
+     */
+    private $comment;
+
+    /**
+     * The encoding.
+     *
+     * This should be one of 'ASCII', 'JIS', 'Unicode', or ''.
+     *
+     * @var string
+     */
+    private $encoding;
+
+    /**
+     * Make a new entry for holding a user comment.
+     *
+     * @param
+     *            string the new user comment.
+     *
+     * @param
+     *            string the encoding of the comment. This should be either
+     *            'ASCII', 'JIS', 'Unicode', or the empty string specifying an
+     *            undefined encoding.
+     */
+    public function __construct($comment = '', $encoding = 'ASCII')
+    {
+        parent::__construct(PelTag::USER_COMMENT);
+        $this->setValue($comment, $encoding);
+    }
+
+    /**
+     * Set the user comment.
+     *
+     * @param
+     *            string the new user comment.
+     *
+     * @param
+     *            string the encoding of the comment. This should be either
+     *            'ASCII', 'JIS', 'Unicode', or the empty string specifying an
+     *            unknown encoding.
+     */
+    public function setValue($comment = '', $encoding = 'ASCII')
+    {
+        $this->comment = $comment;
+        $this->encoding = $encoding;
+        parent::setValue(str_pad($encoding, 8, chr(0)) . $comment);
+    }
+
+    /**
+     * Returns the user comment.
+     *
+     * The comment is returned with the same character encoding as when
+     * it was set using {@link setValue} or {@link __construct the
+     * constructor}.
+     *
+     * @return string the user comment.
+     */
+    public function getValue()
+    {
+        return $this->comment;
+    }
+
+    /**
+     * Returns the encoding.
+     *
+     * @return string the encoding of the user comment.
+     */
+    public function getEncoding()
+    {
+        return $this->encoding;
+    }
+
+    /**
+     * Returns the user comment.
+     *
+     * @return string the user comment.
+     */
+    public function getText($brief = false)
+    {
+        return $this->comment;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryVersion.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryVersion.php
new file mode 100644
index 0000000000000000000000000000000000000000..0edd269650caf4f8d3a487c94d02a27d69310a9d
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryVersion.php
@@ -0,0 +1,182 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold data for Exif tags of format undefined.
+ *
+ * This file contains the base class {@link PelEntryUndefined} and
+ * the subclasses {@link PelEntryUserComment} which should be used
+ * to manage the {@link PelTag::USER_COMMENT} tag, and {@link
+ * PelEntryVersion} which is used to manage entries with version
+ * information.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class to hold version information.
+ *
+ * There are three Exif entries that hold version information: the
+ * {@link PelTag::EXIF_VERSION}, {@link
+ * PelTag::FLASH_PIX_VERSION}, and {@link
+ * PelTag::INTEROPERABILITY_VERSION} tags. This class manages
+ * those tags.
+ *
+ * The class is used in a very straight-forward way:
+ * <code>
+ * $entry = new PelEntryVersion(PelTag::EXIF_VERSION, 2.2);
+ * </code>
+ * This creates an entry for an file complying to the Exif 2.2
+ * standard. It is easy to test for standards level of an unknown
+ * entry:
+ * <code>
+ * if ($entry->getTag() == PelTag::EXIF_VERSION &&
+ * $entry->getValue() > 2.0) {
+ * echo 'Recent Exif version.';
+ * }
+ * </code>
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryVersion extends PelEntry
+{
+
+    /**
+     * The version held by this entry.
+     *
+     * @var float
+     */
+    private $version;
+
+    /**
+     * Make a new entry for holding a version.
+     *
+     * @param integer $tag
+     *            This should be one of {@link
+     *            PelTag::EXIF_VERSION}, {@link PelTag::FLASH_PIX_VERSION},
+     *            or {@link PelTag::INTEROPERABILITY_VERSION}.
+     *
+     * @param float $version
+     *            The size of the entries leave room for
+     *            exactly four digits: two digits on either side of the decimal
+     *            point.
+     */
+    public function __construct($tag, $version = 0.0)
+    {
+        $this->tag = $tag;
+        $this->format = PelFormat::UNDEFINED;
+        $this->setValue($version);
+    }
+
+    /**
+     * Set the version held by this entry.
+     *
+     * @param float $version
+     *            The size of the entries leave room for
+     *            exactly four digits: two digits on either side of the decimal
+     *            point.
+     */
+    public function setValue($version = 0.0)
+    {
+        $this->version = $version;
+        $major = floor($version);
+        $minor = ($version - $major) * 100;
+        $strValue = sprintf('%02.0f%02.0f', $major, $minor);
+        $this->components = strlen($strValue);
+        $this->bytes = $strValue;
+    }
+
+    /**
+     * Return the version held by this entry.
+     *
+     * @return float This will be the same as the value
+     *         given to {@link setValue} or {@link __construct the
+     *         constructor}.
+     */
+    public function getValue()
+    {
+        return $this->version;
+    }
+
+    /**
+     * Return a text string with the version.
+     *
+     * @param boolean $brief
+     *            controls if the output should be brief. Brief
+     *            output omits the word 'Version' so the result is just 'Exif x.y'
+     *            instead of 'Exif Version x.y' if the entry holds information
+     *            about the Exif version --- the output for FlashPix is similar.
+     *
+     * @return string the version number with the type of the tag,
+     *         either 'Exif' or 'FlashPix'.
+     */
+    public function getText($brief = false)
+    {
+        $v = $this->version;
+
+        /*
+         * Versions numbers like 2.0 would be output as just 2 if we don't
+         * add the '.0' ourselves.
+         */
+        if (floor($this->version) == $this->version) {
+            $v .= '.0';
+        }
+
+        switch ($this->tag) {
+            case PelTag::EXIF_VERSION:
+                if ($brief) {
+                    return Pel::fmt('Exif %s', $v);
+                } else {
+                    return Pel::fmt('Exif Version %s', $v);
+                }
+                break;
+            case PelTag::FLASH_PIX_VERSION:
+                if ($brief) {
+                    return Pel::fmt('FlashPix %s', $v);
+                } else {
+                    return Pel::fmt('FlashPix Version %s', $v);
+                }
+                break;
+            case PelTag::INTEROPERABILITY_VERSION:
+                if ($brief) {
+                    return Pel::fmt('Interoperability %s', $v);
+                } else {
+                    return Pel::fmt('Interoperability Version %s', $v);
+                }
+                break;
+        }
+
+        if ($brief) {
+            return $v;
+        } else {
+            return Pel::fmt('Version %s', $v);
+        }
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryWindowsString.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryWindowsString.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f043493c0db5be7fdd8f08f3d291bf63304b213
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelEntryWindowsString.php
@@ -0,0 +1,161 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes used to hold bytes, both signed and unsigned.
+ * The {@link
+ * PelEntryWindowsString} class is used to manipulate strings in the
+ * format Windows XP needs.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class used to manipulate strings in the format Windows XP uses.
+ *
+ * When examining the file properties of an image in Windows XP one
+ * can fill in title, comment, author, keyword, and subject fields.
+ * Filling those fields and pressing OK will result in the data being
+ * written into the Exif data in the image.
+ *
+ * The data is written in a non-standard format and can thus not be
+ * loaded directly --- this class is needed to translate it into
+ * normal strings.
+ *
+ * It is important that entries from this class are only created with
+ * the {@link PelTag::XP_TITLE}, {@link PelTag::XP_COMMENT}, {@link
+ * PelTag::XP_AUTHOR}, {@link PelTag::XP_KEYWORD}, and {@link
+ * PelTag::XP_SUBJECT} tags. If another tag is used the data will no
+ * longer be correctly decoded when reloaded with PEL. (The data will
+ * be loaded as an {@link PelEntryByte} entry, which isn't as useful.)
+ *
+ * This class is to be used as in
+ * <code>
+ * $title = $ifd->getEntry(PelTag::XP_TITLE);
+ * print($title->getValue());
+ * $title->setValue('My favorite cat');
+ * </code>
+ * or if no entry is present one can add a new one with
+ * <code>
+ * $title = new PelEntryWindowsString(PelTag::XP_TITLE, 'A cute dog.');
+ * $ifd->addEntry($title);
+ * </code>
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelEntryWindowsString extends PelEntry
+{
+
+    /**
+     * The string hold by this entry.
+     *
+     * This is the string that was given to the {@link __construct
+     * constructor} or later to {@link setValue}, without any extra NULL
+     * characters or any such nonsense.
+     *
+     * @var string
+     */
+    private $str;
+
+    /**
+     * Make a new PelEntry that can hold a Windows XP specific string.
+     *
+     * @param int $tag
+     *            the tag which this entry represents. This should be
+     *            one of {@link PelTag::XP_TITLE}, {@link PelTag::XP_COMMENT},
+     *            {@link PelTag::XP_AUTHOR}, {@link PelTag::XP_KEYWORD}, and {@link
+     *            PelTag::XP_SUBJECT} tags. If another tag is used, then this
+     *            entry will be incorrectly reloaded as a {@link PelEntryByte}.
+     *
+     * @param string $str
+     *            the string that this entry will represent. It will
+     *            be passed to {@link setValue} and thus has to obey its
+     *            requirements.
+     */
+    public function __construct($tag, $str = '')
+    {
+        $this->tag = $tag;
+        $this->format = PelFormat::BYTE;
+        $this->setValue($str);
+    }
+
+    /**
+     * Give the entry a new value.
+     *
+     * This will overwrite the previous value. The value can be
+     * retrieved later with the {@link getValue} method.
+     *
+     * @param string $str
+     *            the new value of the entry. This should be use the
+     *            Latin-1 encoding and be given without any extra NULL characters.
+     */
+    public function setValue($str)
+    {
+        $l = strlen($str);
+
+        $this->components = 2 * ($l + 1);
+        $this->str = $str;
+        $this->bytes = '';
+        for ($i = 0; $i < $l; $i ++) {
+            $this->bytes .= $str{$i} . chr(0x00);
+        }
+
+        $this->bytes .= chr(0x00) . chr(0x00);
+    }
+
+    /**
+     * Return the string of the entry.
+     *
+     * @return string the string held, without any extra NULL
+     *         characters. The string will be the same as the one given to
+     *         {@link setValue} or to the {@link __construct constructor}.
+     */
+    public function getValue()
+    {
+        return $this->str;
+    }
+
+    /**
+     * Return the string of the entry.
+     *
+     * This methods returns the same as {@link getValue}.
+     *
+     * @param boolean $brief
+     *            not used.
+     *
+     * @return string the string held, without any extra NULL
+     *         characters. The string will be the same as the one given to
+     *         {@link setValue} or to the {@link __construct constructor}.
+     */
+    public function getText($brief = false)
+    {
+        return $this->str;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelException.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b663e3cfd5e8668360063967db0d13319975266
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelException.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Standard PEL printf() capable exception.
+ * This class is a simple extension of the standard Exception class in
+ * PHP, and all the methods defined there retain their original
+ * meaning.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ *
+ * @subpackage PelException
+ */
+class PelException extends \Exception
+{
+
+    /**
+     * Construct a new PEL exception.
+     *
+     * @param string $fmt
+     *            an optional format string can be given. It
+     *            will be used as a format string for vprintf(). The remaining
+     *            arguments will be available for the format string as usual with
+     *            vprintf().
+     *
+     * @param mixed ...$args
+     *            any number of arguments to be used with
+     *            the format string.
+     */
+    public function __construct($fmt, $args = null)
+    {
+        $args = func_get_args();
+        $fmt = array_shift($args);
+        parent::__construct(vsprintf($fmt, $args));
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelExif.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelExif.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7deb2a43a4bc68c9f5ae86bd03591938f27d136
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelExif.php
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif data.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class representing Exif data.
+ *
+ * Exif data resides as {@link PelJpegContent data} and consists of a
+ * header followed by a number of {@link PelJpegIfd IFDs}.
+ *
+ * The interesting method in this class is {@link getTiff()} which
+ * will return the {@link PelTiff} object which really holds the data
+ * which one normally think of when talking about Exif data. This is
+ * because Exif data is stored as an extension of the TIFF file
+ * format.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelExif extends PelJpegContent
+{
+
+    /**
+     * Exif header.
+     *
+     * The Exif data must start with these six bytes to be considered
+     * valid.
+     */
+    const EXIF_HEADER = "Exif\0\0";
+
+    /**
+     * The PelTiff object contained within.
+     *
+     * @var PelTiff
+     */
+    private $tiff = null;
+
+    /**
+     * Construct a new Exif object.
+     *
+     * The new object will be empty --- use the {@link load()} method to
+     * load Exif data from a {@link PelDataWindow} object, or use the
+     * {@link setTiff()} to change the {@link PelTiff} object, which is
+     * the true holder of the Exif {@link PelEntry entries}.
+     */
+    public function __construct()
+    {
+        // nothing to be done
+    }
+
+    /**
+     * Load and parse Exif data.
+     *
+     * This will populate the object with Exif data, contained as a
+     * {@link PelTiff} object. This TIFF object can be accessed with
+     * the {@link getTiff()} method.
+     *
+     * @param PelDataWindow $d
+     */
+    public function load(PelDataWindow $d)
+    {
+        Pel::debug('Parsing %d bytes of Exif data...', $d->getSize());
+
+        /* There must be at least 6 bytes for the Exif header. */
+        if ($d->getSize() < 6) {
+            throw new PelInvalidDataException('Expected at least 6 bytes of Exif ' . 'data, found just %d bytes.', $d->getSize());
+        }
+        /* Verify the Exif header */
+        if ($d->strcmp(0, self::EXIF_HEADER)) {
+            $d->setWindowStart(strlen(self::EXIF_HEADER));
+        } else {
+            throw new PelInvalidDataException('Exif header not found.');
+        }
+
+        /* The rest of the data is TIFF data. */
+        $this->tiff = new PelTiff();
+        $this->tiff->load($d);
+    }
+
+    /**
+     * Change the TIFF information.
+     *
+     * Exif data is really stored as TIFF data, and this method can be
+     * used to change this data from one {@link PelTiff} object to
+     * another.
+     *
+     * @param PelTiff $tiff
+     *            the new TIFF object.
+     */
+    public function setTiff(PelTiff $tiff)
+    {
+        $this->tiff = $tiff;
+    }
+
+    /**
+     * Get the underlying TIFF object.
+     *
+     * The actual Exif data is stored in a {@link PelTiff} object, and
+     * this method provides access to it.
+     *
+     * @return PelTiff the TIFF object with the Exif data.
+     */
+    public function getTiff()
+    {
+        return $this->tiff;
+    }
+
+    /**
+     * Produce bytes for the Exif data.
+     *
+     * @return string bytes representing this object.
+     */
+    public function getBytes()
+    {
+        return self::EXIF_HEADER . $this->tiff->getBytes();
+    }
+
+    /**
+     * Return a string representation of this object.
+     *
+     * @return string a string describing this object. This is mostly
+     *         useful for debugging.
+     */
+    public function __toString()
+    {
+        return Pel::tra("Dumping Exif data...\n") . $this->tiff->__toString();
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelFormat.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelFormat.php
new file mode 100644
index 0000000000000000000000000000000000000000..aa9caa3cca5b95c08e140ce2f9add30c749d9e1d
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelFormat.php
@@ -0,0 +1,227 @@
+<?php
+/*
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ * Copyright (C) 2017 Johannes Weberhofer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Namespace for functions operating on Exif formats.
+ *
+ * This class defines the constants that are to be used whenever one
+ * has to refer to the format of an Exif tag. They will be
+ * collectively denoted by the pseudo-type PelFormat throughout the
+ * documentation.
+ *
+ * All the methods defined here are static, and they all operate on a
+ * single argument which should be one of the class constants.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @author Johannes Weberhofer <jweberhofer@weberhofer.at>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package
+ *
+ */
+class PelFormat
+{
+
+    /**
+     * Unsigned byte.
+     *
+     * Each component will be an unsigned 8-bit integer with a value
+     * between 0 and 255.
+     *
+     * Modelled with the {@link PelEntryByte} class.
+     */
+    const BYTE = 1;
+
+    /**
+     * ASCII string.
+     *
+     * Each component will be an ASCII character.
+     *
+     * Modelled with the {@link PelEntryAscii} class.
+     */
+    const ASCII = 2;
+
+    /**
+     * Unsigned short.
+     *
+     * Each component will be an unsigned 16-bit integer with a value
+     * between 0 and 65535.
+     *
+     * Modelled with the {@link PelEntryShort} class.
+     */
+    const SHORT = 3;
+
+    /**
+     * Unsigned long.
+     *
+     * Each component will be an unsigned 32-bit integer with a value
+     * between 0 and 4294967295.
+     *
+     * Modelled with the {@link PelEntryLong} class.
+     */
+    const LONG = 4;
+
+    /**
+     * Unsigned rational number.
+     *
+     * Each component will consist of two unsigned 32-bit integers
+     * denoting the enumerator and denominator. Each integer will have
+     * a value between 0 and 4294967295.
+     *
+     * Modelled with the {@link PelEntryRational} class.
+     */
+    const RATIONAL = 5;
+
+    /**
+     * Signed byte.
+     *
+     * Each component will be a signed 8-bit integer with a value
+     * between -128 and 127.
+     *
+     * Modelled with the {@link PelEntrySByte} class.
+     */
+    const SBYTE = 6;
+
+    /**
+     * Undefined byte.
+     *
+     * Each component will be a byte with no associated interpretation.
+     *
+     * Modelled with the {@link PelEntryUndefined} class.
+     */
+    const UNDEFINED = 7;
+
+    /**
+     * Signed short.
+     *
+     * Each component will be a signed 16-bit integer with a value
+     * between -32768 and 32767.
+     *
+     * Modelled with the {@link PelEntrySShort} class.
+     */
+    const SSHORT = 8;
+
+    /**
+     * Signed long.
+     *
+     * Each component will be a signed 32-bit integer with a value
+     * between -2147483648 and 2147483647.
+     *
+     * Modelled with the {@link PelEntrySLong} class.
+     */
+    const SLONG = 9;
+
+    /**
+     * Signed rational number.
+     *
+     * Each component will consist of two signed 32-bit integers
+     * denoting the enumerator and denominator. Each integer will have
+     * a value between -2147483648 and 2147483647.
+     *
+     * Modelled with the {@link PelEntrySRational} class.
+     */
+    const SRATIONAL = 10;
+
+    /**
+     * Floating point number.
+     *
+     * Entries with this format are not currently implemented.
+     */
+    const FLOAT = 11;
+
+    /**
+     * Double precision floating point number.
+     *
+     * Entries with this format are not currently implemented.
+     */
+    const DOUBLE = 12;
+
+    /**
+     * Values for format's short names
+     */
+    protected static $formatName = array(
+        self::ASCII => 'Ascii',
+        self::BYTE => 'Byte',
+        self::SHORT => 'Short',
+        self::LONG => 'Long',
+        self::RATIONAL => 'Rational',
+        self::SBYTE => 'SByte',
+        self::SSHORT => 'SShort',
+        self::SLONG => 'SLong',
+        self::SRATIONAL => 'SRational',
+        self::FLOAT => 'Float',
+        self::DOUBLE => 'Double',
+        self::UNDEFINED => 'Undefined'
+    );
+
+    protected static $formatLength = array(
+        self::ASCII => 1,
+        self::BYTE => 1,
+        self::SHORT => 2,
+        self::LONG => 4,
+        self::RATIONAL => 8,
+        self::SBYTE => 1,
+        self::SSHORT => 2,
+        self::SLONG => 4,
+        self::SRATIONAL => 8,
+        self::FLOAT => 4,
+        self::DOUBLE => 8,
+        self::UNDEFINED => 1
+    );
+
+    /**
+     * Returns the name of a format like 'Ascii' for the {@link ASCII} format
+     *
+     * @param integer $type
+     *            as defined in {@link PelFormat}
+     * @return string
+     */
+    public static function getName($type)
+    {
+        if (array_key_exists($type, self::$formatName)) {
+            return self::$formatName[$type];
+        } else {
+            return Pel::fmt('Unknown format: 0x%X', $type);
+        }
+    }
+
+    /**
+     * Return the size of components in a given format in bytes needed to store one component with the
+     * given format.
+     *
+     * @param integer $type
+     *            as defined in {@link PelFormat}
+     * @return integer|string
+     */
+    public static function getSize($type)
+    {
+        if (array_key_exists($type, self::$formatLength)) {
+            return self::$formatLength[$type];
+        } else {
+            return Pel::fmt('Unknown format: 0x%X', $type);
+        }
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelIfd.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelIfd.php
new file mode 100644
index 0000000000000000000000000000000000000000..86b517642e0ba1dab8ff6bea4f42acb824ac5f3e
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelIfd.php
@@ -0,0 +1,1221 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif IFDs.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class representing an Image File Directory (IFD).
+ *
+ * {@link PelTiff TIFF data} is structured as a number of Image File
+ * Directories, IFDs for short. Each IFD contains a number of {@link
+ * PelEntry entries}, some data and finally a link to the next IFD.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelIfd implements \IteratorAggregate, \ArrayAccess
+{
+
+    /**
+     * Main image IFD.
+     *
+     * Pass this to the constructor when creating an IFD which will be
+     * the IFD of the main image.
+     */
+    const IFD0 = 0;
+
+    /**
+     * Thumbnail image IFD.
+     *
+     * Pass this to the constructor when creating an IFD which will be
+     * the IFD of the thumbnail image.
+     */
+    const IFD1 = 1;
+
+    /**
+     * Exif IFD.
+     *
+     * Pass this to the constructor when creating an IFD which will be
+     * the Exif sub-IFD.
+     */
+    const EXIF = 2;
+
+    /**
+     * GPS IFD.
+     *
+     * Pass this to the constructor when creating an IFD which will be
+     * the GPS sub-IFD.
+     */
+    const GPS = 3;
+
+    /**
+     * Interoperability IFD.
+     *
+     * Pass this to the constructor when creating an IFD which will be
+     * the interoperability sub-IFD.
+     */
+    const INTEROPERABILITY = 4;
+
+    /**
+     * The entries held by this directory.
+     *
+     * Each tag in the directory is represented by a {@link PelEntry}
+     * object in this array.
+     *
+     * @var array
+     */
+    private $entries = array();
+
+    /**
+     * The type of this directory.
+     *
+     * Initialized in the constructor. Must be one of {@link IFD0},
+     * {@link IFD1}, {@link EXIF}, {@link GPS}, or {@link
+     * INTEROPERABILITY}.
+     *
+     * @var int
+     */
+    private $type;
+
+    /**
+     * The next directory.
+     *
+     * This will be initialized in the constructor, or be left as null
+     * if this is the last directory.
+     *
+     * @var PelIfd
+     */
+    private $next = null;
+
+    /**
+     * Sub-directories pointed to by this directory.
+     *
+     * This will be an array of ({@link PelTag}, {@link PelIfd}) pairs.
+     *
+     * @var array
+     */
+    private $sub = array();
+
+    /**
+     * The thumbnail data.
+     *
+     * This will be initialized in the constructor, or be left as null
+     * if there are no thumbnail as part of this directory.
+     *
+     * @var PelDataWindow
+     */
+    private $thumb_data = null;
+    // TODO: use this format to choose between the
+    // JPEG_INTERCHANGE_FORMAT and STRIP_OFFSETS tags.
+    // private $thumb_format;
+
+    /**
+     * Construct a new Image File Directory (IFD).
+     *
+     * The IFD will be empty, use the {@link addEntry()} method to add
+     * an {@link PelEntry}. Use the {@link setNext()} method to link
+     * this IFD to another.
+     *
+     * @param
+     *            int type the type of this IFD. Must be one of {@link
+     *            IFD0}, {@link IFD1}, {@link EXIF}, {@link GPS}, or {@link
+     *            INTEROPERABILITY}. An {@link PelIfdException} will be thrown
+     *            otherwise.
+     */
+    public function __construct($type)
+    {
+        if ($type != PelIfd::IFD0 && $type != PelIfd::IFD1 && $type != PelIfd::EXIF && $type != PelIfd::GPS &&
+             $type != PelIfd::INTEROPERABILITY) {
+            throw new PelIfdException('Unknown IFD type: %d', $type);
+        }
+
+        $this->type = $type;
+    }
+
+    /**
+     * Load data into a Image File Directory (IFD).
+     *
+     * @param PelDataWindow $d
+     *            the data window that will provide the data.
+     *
+     * @param int $offset
+     *            the offset within the window where the directory will
+     *            be found.
+     */
+    public function load(PelDataWindow $d, $offset)
+    {
+        $thumb_offset = 0;
+        $thumb_length = 0;
+
+        Pel::debug('Constructing IFD at offset %d from %d bytes...', $offset, $d->getSize());
+
+        /* Read the number of entries */
+        $n = $d->getShort($offset);
+        Pel::debug('Loading %d entries...', $n);
+
+        $offset += 2;
+
+        /* Check if we have enough data. */
+        if ($offset + 12 * $n > $d->getSize()) {
+            $n = floor(($offset - $d->getSize()) / 12);
+            Pel::maybeThrow(new PelIfdException('Adjusted to: %d.', $n));
+        }
+
+        for ($i = 0; $i < $n; $i ++) {
+            // TODO: increment window start instead of using offsets.
+            $tag = $d->getShort($offset + 12 * $i);
+            Pel::debug(
+                'Loading entry with tag 0x%04X: %s (%d of %d)...',
+                $tag,
+                PelTag::getName($this->type, $tag),
+                $i + 1,
+                $n);
+
+            switch ($tag) {
+                case PelTag::EXIF_IFD_POINTER:
+                case PelTag::GPS_INFO_IFD_POINTER:
+                case PelTag::INTEROPERABILITY_IFD_POINTER:
+                    $o = $d->getLong($offset + 12 * $i + 8);
+                    Pel::debug('Found sub IFD at offset %d', $o);
+
+                    /* Map tag to IFD type. */
+                    if ($tag == PelTag::EXIF_IFD_POINTER) {
+                        $type = PelIfd::EXIF;
+                    } elseif ($tag == PelTag::GPS_INFO_IFD_POINTER) {
+                        $type = PelIfd::GPS;
+                    } elseif ($tag == PelTag::INTEROPERABILITY_IFD_POINTER) {
+                        $type = PelIfd::INTEROPERABILITY;
+                    }
+
+                    $this->sub[$type] = new PelIfd($type);
+                    $this->sub[$type]->load($d, $o);
+                    break;
+                case PelTag::JPEG_INTERCHANGE_FORMAT:
+                    $thumb_offset = $d->getLong($offset + 12 * $i + 8);
+                    $this->safeSetThumbnail($d, $thumb_offset, $thumb_length);
+                    break;
+                case PelTag::JPEG_INTERCHANGE_FORMAT_LENGTH:
+                    $thumb_length = $d->getLong($offset + 12 * $i + 8);
+                    $this->safeSetThumbnail($d, $thumb_offset, $thumb_length);
+                    break;
+                default:
+                    $format = $d->getShort($offset + 12 * $i + 2);
+                    $components = $d->getLong($offset + 12 * $i + 4);
+
+                    /*
+                     * The data size. If bigger than 4 bytes, the actual data is
+                     * not in the entry but somewhere else, with the offset stored
+                     * in the entry.
+                     */
+                    $s = PelFormat::getSize($format) * $components;
+                    if ($s > 0) {
+                        $doff = $offset + 12 * $i + 8;
+                        if ($s > 4) {
+                            $doff = $d->getLong($doff);
+                        }
+                        $data = $d->getClone($doff, $s);
+                    } else {
+                        $data = new PelDataWindow();
+                    }
+
+                    try {
+                        $entry = $this->newEntryFromData($tag, $format, $components, $data);
+                        $this->addEntry($entry);
+                    } catch (PelException $e) {
+                        /*
+                         * Throw the exception when running in strict mode, store
+                         * otherwise.
+                         */
+                        Pel::maybeThrow($e);
+                    }
+
+                    /* The format of the thumbnail is stored in this tag. */
+                    // TODO: handle TIFF thumbnail.
+                    // if ($tag == PelTag::COMPRESSION) {
+                    // $this->thumb_format = $data->getShort();
+                    // }
+                    break;
+            }
+        }
+
+        /* Offset to next IFD */
+        $o = $d->getLong($offset + 12 * $n);
+        Pel::debug('Current offset is %d, link at %d points to %d.', $offset, $offset + 12 * $n, $o);
+
+        if ($o > 0) {
+            /* Sanity check: we need 6 bytes */
+            if ($o > $d->getSize() - 6) {
+                Pel::maybeThrow(new PelIfdException('Bogus offset to next IFD: ' . '%d > %d!', $o, $d->getSize() - 6));
+            } else {
+                if ($this->type == PelIfd::IFD1) {
+                    // IFD1 shouldn't link further...
+                    Pel::maybeThrow(new PelIfdException('IFD1 links to another IFD!'));
+                }
+                $this->next = new PelIfd(PelIfd::IFD1);
+                $this->next->load($d, $o);
+            }
+        } else {
+            Pel::debug('Last IFD.');
+        }
+    }
+
+    /**
+     * Make a new entry from a bunch of bytes.
+     *
+     * This method will create the proper subclass of {@link PelEntry}
+     * corresponding to the {@link PelTag} and {@link PelFormat} given.
+     * The entry will be initialized with the data given.
+     *
+     * Please note that the data you pass to this method should come
+     * from an image, that is, it should be raw bytes. If instead you
+     * want to create an entry for holding, say, an short integer, then
+     * create a {@link PelEntryShort} object directly and load the data
+     * into it.
+     *
+     * A {@link PelUnexpectedFormatException} is thrown if a mismatch is
+     * discovered between the tag and format, and likewise a {@link
+     * PelWrongComponentCountException} is thrown if the number of
+     * components does not match the requirements of the tag. The
+     * requirements for a given tag (if any) can be found in the
+     * documentation for {@link PelTag}.
+     *
+     * @param integer $tag
+     *            the tag of the entry as defined in {@link PelTag}.
+     *
+     * @param integer $format
+     *            the format of the entry as defined in {@link PelFormat}.
+     *
+     * @param int $components
+     *            the components in the entry.
+     *
+     * @param PelDataWindow $data
+     *            the data which will be used to construct the
+     *            entry.
+     *
+     * @return PelEntry a newly created entry, holding the data given.
+     */
+    public function newEntryFromData($tag, $format, $components, PelDataWindow $data)
+    {
+
+        /*
+         * First handle tags for which we have a specific PelEntryXXX
+         * class.
+         */
+        switch ($this->type) {
+            case self::IFD0:
+            case self::IFD1:
+            case self::EXIF:
+            case self::INTEROPERABILITY:
+                switch ($tag) {
+                    case PelTag::DATE_TIME:
+                    case PelTag::DATE_TIME_ORIGINAL:
+                    case PelTag::DATE_TIME_DIGITIZED:
+                        if ($format != PelFormat::ASCII) {
+                            throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::ASCII);
+                        }
+                        if ($components != 20) {
+                            throw new PelWrongComponentCountException($this->type, $tag, $components, 20);
+                        }
+                        // TODO: handle timezones.
+                        return new PelEntryTime($tag, $data->getBytes(0, - 1), PelEntryTime::EXIF_STRING);
+
+                    case PelTag::COPYRIGHT:
+                        if ($format != PelFormat::ASCII) {
+                            throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::ASCII);
+                        }
+                        $v = explode("\0", trim($data->getBytes(), ' '));
+                        if (! isset($v[1])) {
+                            Pel::maybeThrow(new PelException('Invalid copyright: %s', $data->getBytes()));
+                            // when not in strict mode, set empty copyright and continue
+                            $v[1] = '';
+                        }
+                        return new PelEntryCopyright($v[0], $v[1]);
+
+                    case PelTag::EXIF_VERSION:
+                    case PelTag::FLASH_PIX_VERSION:
+                    case PelTag::INTEROPERABILITY_VERSION:
+                        if ($format != PelFormat::UNDEFINED) {
+                            throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::UNDEFINED);
+                        }
+                        return new PelEntryVersion($tag, $data->getBytes() / 100);
+
+                    case PelTag::USER_COMMENT:
+                        if ($format != PelFormat::UNDEFINED) {
+                            throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::UNDEFINED);
+                        }
+                        if ($data->getSize() < 8) {
+                            return new PelEntryUserComment();
+                        } else {
+                            return new PelEntryUserComment($data->getBytes(8), rtrim($data->getBytes(0, 8)));
+                        }
+                    // this point can not be reached
+                    case PelTag::XP_TITLE:
+                    case PelTag::XP_COMMENT:
+                    case PelTag::XP_AUTHOR:
+                    case PelTag::XP_KEYWORDS:
+                    case PelTag::XP_SUBJECT:
+                        if ($format != PelFormat::BYTE) {
+                            throw new PelUnexpectedFormatException($this->type, $tag, $format, PelFormat::BYTE);
+                        }
+                        $v = '';
+                        for ($i = 0; $i < $components; $i ++) {
+                            $b = $data->getByte($i);
+                            /*
+                             * Convert the byte to a character if it is non-null ---
+                             * information about the character encoding of these entries
+                             * would be very nice to have! So far my tests have shown
+                             * that characters in the Latin-1 character set are stored in
+                             * a single byte followed by a NULL byte.
+                             */
+                            if ($b != 0) {
+                                $v .= chr($b);
+                            }
+                        }
+
+                        return new PelEntryWindowsString($tag, $v);
+                }
+            // This point can be reached! Continue with default.
+            case self::GPS:
+            default:
+                /* Then handle the basic formats. */
+                switch ($format) {
+                    case PelFormat::BYTE:
+                        $v = new PelEntryByte($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getByte($i));
+                        }
+                        return $v;
+
+                    case PelFormat::SBYTE:
+                        $v = new PelEntrySByte($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getSByte($i));
+                        }
+                        return $v;
+
+                    case PelFormat::ASCII:
+                        return new PelEntryAscii($tag, rtrim($data->getBytes(0), "\0"));
+
+                    case PelFormat::SHORT:
+                        $v = new PelEntryShort($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getShort($i * 2));
+                        }
+                        return $v;
+
+                    case PelFormat::SSHORT:
+                        $v = new PelEntrySShort($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getSShort($i * 2));
+                        }
+                        return $v;
+
+                    case PelFormat::LONG:
+                        $v = new PelEntryLong($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getLong($i * 4));
+                        }
+                        return $v;
+
+                    case PelFormat::SLONG:
+                        $v = new PelEntrySLong($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getSLong($i * 4));
+                        }
+                        return $v;
+
+                    case PelFormat::RATIONAL:
+                        $v = new PelEntryRational($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getRational($i * 8));
+                        }
+                        return $v;
+
+                    case PelFormat::SRATIONAL:
+                        $v = new PelEntrySRational($tag);
+                        for ($i = 0; $i < $components; $i ++) {
+                            $v->addNumber($data->getSRational($i * 8));
+                        }
+                        return $v;
+
+                    case PelFormat::UNDEFINED:
+                        return new PelEntryUndefined($tag, $data->getBytes());
+
+                    default:
+                        throw new PelException('Unsupported format: %s', PelFormat::getName($format));
+                }
+        }
+    }
+
+    /**
+     * Extract thumbnail data safely.
+     *
+     * It is safe to call this method repeatedly with either the offset
+     * or the length set to zero, since it requires both of these
+     * arguments to be positive before the thumbnail is extracted.
+     *
+     * When both parameters are set it will check the length against the
+     * available data and adjust as necessary. Only then is the
+     * thumbnail data loaded.
+     *
+     * @param PelDataWindow $d
+     *            the data from which the thumbnail will be
+     *            extracted.
+     *
+     * @param int $offset
+     *            the offset into the data.
+     *
+     * @param int $length
+     *            the length of the thumbnail.
+     */
+    private function safeSetThumbnail(PelDataWindow $d, $offset, $length)
+    {
+        /*
+         * Load the thumbnail if both the offset and the length is
+         * available.
+         */
+        if ($offset > 0 && $length > 0) {
+            /*
+             * Some images have a broken length, so we try to carefully
+             * check the length before we store the thumbnail.
+             */
+            if ($offset + $length > $d->getSize()) {
+                Pel::maybeThrow(
+                    new PelIfdException(
+                        'Thumbnail length %d bytes ' . 'adjusted to %d bytes.',
+                        $length,
+                        $d->getSize() - $offset));
+                $length = $d->getSize() - $offset;
+            }
+
+            /* Now set the thumbnail normally. */
+            $this->setThumbnail($d->getClone($offset, $length));
+        }
+    }
+
+    /**
+     * Set thumbnail data.
+     *
+     * Use this to embed an arbitrary JPEG image within this IFD. The
+     * data will be checked to ensure that it has a proper {@link
+     * PelJpegMarker::EOI} at the end. If not, then the length is
+     * adjusted until one if found. An {@link PelIfdException} might be
+     * thrown (depending on {@link Pel::$strict}) this case.
+     *
+     * @param PelDataWindow $d
+     *            the thumbnail data.
+     */
+    public function setThumbnail(PelDataWindow $d)
+    {
+        $size = $d->getSize();
+        /* Now move backwards until we find the EOI JPEG marker. */
+        while ($d->getByte($size - 2) != 0xFF || $d->getByte($size - 1) != PelJpegMarker::EOI) {
+            $size --;
+        }
+
+        if ($size != $d->getSize()) {
+            Pel::maybeThrow(new PelIfdException('Decrementing thumbnail size ' . 'to %d bytes', $size));
+        }
+        $this->thumb_data = $d->getClone(0, $size);
+    }
+
+    /**
+     * Get the type of this directory.
+     *
+     * @return int of {@link PelIfd::IFD0}, {@link PelIfd::IFD1}, {@link
+     *         PelIfd::EXIF}, {@link PelIfd::GPS}, or {@link
+     *         PelIfd::INTEROPERABILITY}.
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * Is a given tag valid for this IFD?
+     *
+     * Different types of IFDs can contain different kinds of tags ---
+     * the {@link IFD0} type, for example, cannot contain a {@link
+     * PelTag::GPS_LONGITUDE} tag.
+     *
+     * A special exception is tags with values above 0xF000. They are
+     * treated as private tags and will be allowed everywhere (use this
+     * for testing or for implementing your own types of tags).
+     *
+     * @param PelTag $tag
+     *            the tag.
+     *
+     * @return boolean true if the tag is considered valid in this IFD,
+     *         false otherwise.
+     *
+     * @see getValidTags()
+     */
+    public function isValidTag($tag)
+    {
+        return $tag > 0xF000 || in_array($tag, $this->getValidTags());
+    }
+
+    /**
+     * Returns a list of valid tags for this IFD.
+     *
+     * @return array an array of {@link PelTag}s which are valid for
+     *         this IFD.
+     */
+    public function getValidTags()
+    {
+        switch ($this->type) {
+            case PelIfd::IFD0:
+            case PelIfd::IFD1:
+                return array(
+                    PelTag::IMAGE_WIDTH,
+                    PelTag::IMAGE_LENGTH,
+                    PelTag::BITS_PER_SAMPLE,
+                    PelTag::COMPRESSION,
+                    PelTag::PHOTOMETRIC_INTERPRETATION,
+                    PelTag::DOCUMENT_NAME,
+                    PelTag::IMAGE_DESCRIPTION,
+                    PelTag::MAKE,
+                    PelTag::MODEL,
+                    PelTag::STRIP_OFFSETS,
+                    PelTag::ORIENTATION,
+                    PelTag::SAMPLES_PER_PIXEL,
+                    PelTag::ROWS_PER_STRIP,
+                    PelTag::STRIP_BYTE_COUNTS,
+                    PelTag::X_RESOLUTION,
+                    PelTag::Y_RESOLUTION,
+                    PelTag::PLANAR_CONFIGURATION,
+                    PelTag::RESOLUTION_UNIT,
+                    PelTag::TRANSFER_FUNCTION,
+                    PelTag::SOFTWARE,
+                    PelTag::DATE_TIME,
+                    PelTag::ARTIST,
+                    PelTag::WHITE_POINT,
+                    PelTag::PRIMARY_CHROMATICITIES,
+                    PelTag::JPEG_INTERCHANGE_FORMAT,
+                    PelTag::JPEG_INTERCHANGE_FORMAT_LENGTH,
+                    PelTag::YCBCR_COEFFICIENTS,
+                    PelTag::YCBCR_SUB_SAMPLING,
+                    PelTag::YCBCR_POSITIONING,
+                    PelTag::REFERENCE_BLACK_WHITE,
+                    PelTag::COPYRIGHT,
+                    PelTag::EXIF_IFD_POINTER,
+                    PelTag::GPS_INFO_IFD_POINTER,
+                    PelTag::PRINT_IM,
+                    PelTag::XP_TITLE,
+                    PelTag::XP_COMMENT,
+                    PelTag::XP_AUTHOR,
+                    PelTag::XP_KEYWORDS,
+                    PelTag::XP_SUBJECT,
+                    PelTag::RATING
+                );
+
+            case PelIfd::EXIF:
+                return array(
+                    PelTag::EXPOSURE_TIME,
+                    PelTag::FNUMBER,
+                    PelTag::EXPOSURE_PROGRAM,
+                    PelTag::SPECTRAL_SENSITIVITY,
+                    PelTag::ISO_SPEED_RATINGS,
+                    PelTag::OECF,
+                    PelTag::EXIF_VERSION,
+                    PelTag::DATE_TIME_ORIGINAL,
+                    PelTag::DATE_TIME_DIGITIZED,
+                    PelTag::COMPONENTS_CONFIGURATION,
+                    PelTag::COMPRESSED_BITS_PER_PIXEL,
+                    PelTag::SHUTTER_SPEED_VALUE,
+                    PelTag::APERTURE_VALUE,
+                    PelTag::BRIGHTNESS_VALUE,
+                    PelTag::EXPOSURE_BIAS_VALUE,
+                    PelTag::MAX_APERTURE_VALUE,
+                    PelTag::SUBJECT_DISTANCE,
+                    PelTag::METERING_MODE,
+                    PelTag::LIGHT_SOURCE,
+                    PelTag::FLASH,
+                    PelTag::FOCAL_LENGTH,
+                    PelTag::MAKER_NOTE,
+                    PelTag::USER_COMMENT,
+                    PelTag::SUB_SEC_TIME,
+                    PelTag::SUB_SEC_TIME_ORIGINAL,
+                    PelTag::SUB_SEC_TIME_DIGITIZED,
+                    PelTag::FLASH_PIX_VERSION,
+                    PelTag::COLOR_SPACE,
+                    PelTag::PIXEL_X_DIMENSION,
+                    PelTag::PIXEL_Y_DIMENSION,
+                    PelTag::RELATED_SOUND_FILE,
+                    PelTag::FLASH_ENERGY,
+                    PelTag::SPATIAL_FREQUENCY_RESPONSE,
+                    PelTag::FOCAL_PLANE_X_RESOLUTION,
+                    PelTag::FOCAL_PLANE_Y_RESOLUTION,
+                    PelTag::FOCAL_PLANE_RESOLUTION_UNIT,
+                    PelTag::SUBJECT_LOCATION,
+                    PelTag::EXPOSURE_INDEX,
+                    PelTag::SENSING_METHOD,
+                    PelTag::FILE_SOURCE,
+                    PelTag::SCENE_TYPE,
+                    PelTag::CFA_PATTERN,
+                    PelTag::CUSTOM_RENDERED,
+                    PelTag::EXPOSURE_MODE,
+                    PelTag::WHITE_BALANCE,
+                    PelTag::DIGITAL_ZOOM_RATIO,
+                    PelTag::FOCAL_LENGTH_IN_35MM_FILM,
+                    PelTag::SCENE_CAPTURE_TYPE,
+                    PelTag::GAIN_CONTROL,
+                    PelTag::CONTRAST,
+                    PelTag::SATURATION,
+                    PelTag::SHARPNESS,
+                    PelTag::DEVICE_SETTING_DESCRIPTION,
+                    PelTag::SUBJECT_DISTANCE_RANGE,
+                    PelTag::IMAGE_UNIQUE_ID,
+                    PelTag::INTEROPERABILITY_IFD_POINTER,
+                    PelTag::GAMMA
+                );
+
+            case PelIfd::GPS:
+                return array(
+                    PelTag::GPS_VERSION_ID,
+                    PelTag::GPS_LATITUDE_REF,
+                    PelTag::GPS_LATITUDE,
+                    PelTag::GPS_LONGITUDE_REF,
+                    PelTag::GPS_LONGITUDE,
+                    PelTag::GPS_ALTITUDE_REF,
+                    PelTag::GPS_ALTITUDE,
+                    PelTag::GPS_TIME_STAMP,
+                    PelTag::GPS_SATELLITES,
+                    PelTag::GPS_STATUS,
+                    PelTag::GPS_MEASURE_MODE,
+                    PelTag::GPS_DOP,
+                    PelTag::GPS_SPEED_REF,
+                    PelTag::GPS_SPEED,
+                    PelTag::GPS_TRACK_REF,
+                    PelTag::GPS_TRACK,
+                    PelTag::GPS_IMG_DIRECTION_REF,
+                    PelTag::GPS_IMG_DIRECTION,
+                    PelTag::GPS_MAP_DATUM,
+                    PelTag::GPS_DEST_LATITUDE_REF,
+                    PelTag::GPS_DEST_LATITUDE,
+                    PelTag::GPS_DEST_LONGITUDE_REF,
+                    PelTag::GPS_DEST_LONGITUDE,
+                    PelTag::GPS_DEST_BEARING_REF,
+                    PelTag::GPS_DEST_BEARING,
+                    PelTag::GPS_DEST_DISTANCE_REF,
+                    PelTag::GPS_DEST_DISTANCE,
+                    PelTag::GPS_PROCESSING_METHOD,
+                    PelTag::GPS_AREA_INFORMATION,
+                    PelTag::GPS_DATE_STAMP,
+                    PelTag::GPS_DIFFERENTIAL
+                );
+
+            case PelIfd::INTEROPERABILITY:
+                return array(
+                    PelTag::INTEROPERABILITY_INDEX,
+                    PelTag::INTEROPERABILITY_VERSION,
+                    PelTag::RELATED_IMAGE_FILE_FORMAT,
+                    PelTag::RELATED_IMAGE_WIDTH,
+                    PelTag::RELATED_IMAGE_LENGTH
+                );
+
+            /*
+             * TODO: Where do these tags belong?
+             * PelTag::FILL_ORDER,
+             * PelTag::TRANSFER_RANGE,
+             * PelTag::JPEG_PROC,
+             * PelTag::BATTERY_LEVEL,
+             * PelTag::IPTC_NAA,
+             * PelTag::INTER_COLOR_PROFILE,
+             * PelTag::CFA_REPEAT_PATTERN_DIM,
+             */
+        }
+    }
+
+    /**
+     * Get the name of an IFD type.
+     *
+     * @param int $type
+     *            one of {@link PelIfd::IFD0}, {@link PelIfd::IFD1},
+     *            {@link PelIfd::EXIF}, {@link PelIfd::GPS}, or {@link
+     *            PelIfd::INTEROPERABILITY}.
+     *
+     * @return string the name of type.
+     */
+    public static function getTypeName($type)
+    {
+        switch ($type) {
+            case self::IFD0:
+                return '0';
+            case self::IFD1:
+                return '1';
+            case self::EXIF:
+                return 'Exif';
+            case self::GPS:
+                return 'GPS';
+            case self::INTEROPERABILITY:
+                return 'Interoperability';
+            default:
+                throw new PelIfdException('Unknown IFD type: %d', $type);
+        }
+    }
+
+    /**
+     * Get the name of this directory.
+     *
+     * @return string the name of this directory.
+     */
+    public function getName()
+    {
+        return $this->getTypeName($this->type);
+    }
+
+    /**
+     * Adds an entry to the directory.
+     *
+     * @param PelEntry $e
+     *            the entry that will be added. If the entry is not
+     *            valid in this IFD (as per {@link isValidTag()}) an
+     *            {@link PelInvalidDataException} is thrown.
+     *
+     * @todo The entry will be identified with its tag, so each
+     *       directory can only contain one entry with each tag. Is this a
+     *       bug?
+     */
+    public function addEntry(PelEntry $e)
+    {
+        if ($this->isValidTag($e->getTag())) {
+            $e->setIfdType($this->type);
+            $this->entries[$e->getTag()] = $e;
+        } else {
+            throw new PelInvalidDataException("IFD %s cannot hold\n%s", $this->getName(), $e->__toString());
+        }
+    }
+
+    /**
+     * Does a given tag exist in this IFD?
+     *
+     * This methods is part of the ArrayAccess SPL interface for
+     * overriding array access of objects, it allows you to check for
+     * existance of an entry in the IFD:
+     *
+     * <code>
+     * if (isset($ifd[PelTag::FNUMBER]))
+     * // ... do something with the F-number.
+     * </code>
+     *
+     * @param PelTag $tag
+     *            the offset to check.
+     *
+     * @return boolean whether the tag exists.
+     */
+    public function offsetExists($tag)
+    {
+        return isset($this->entries[$tag]);
+    }
+
+    /**
+     * Retrieve a given tag from this IFD.
+     *
+     * This methods is part of the ArrayAccess SPL interface for
+     * overriding array access of objects, it allows you to read entries
+     * from the IFD the same was as for an array:
+     *
+     * <code>
+     * $entry = $ifd[PelTag::FNUMBER];
+     * </code>
+     *
+     * @param PelTag $tag
+     *            the tag to return. It is an error to ask for a tag
+     *            which is not in the IFD, just like asking for a non-existant
+     *            array entry.
+     *
+     * @return PelEntry the entry.
+     */
+    public function offsetGet($tag)
+    {
+        return $this->entries[$tag];
+    }
+
+    /**
+     * Set or update a given tag in this IFD.
+     *
+     * This methods is part of the ArrayAccess SPL interface for
+     * overriding array access of objects, it allows you to add new
+     * entries or replace esisting entries by doing:
+     *
+     * <code>
+     * $ifd[PelTag::EXPOSURE_BIAS_VALUE] = $entry;
+     * </code>
+     *
+     * Note that the actual array index passed is ignored! Instead the
+     * {@link PelTag} from the entry is used.
+     *
+     * @param PelTag $tag
+     *            the offset to update.
+     *
+     * @param PelEntry $e
+     *            the new value.
+     */
+    public function offsetSet($tag, $e)
+    {
+        if ($e instanceof PelEntry) {
+            $tag = $e->getTag();
+            $this->entries[$tag] = $e;
+        } else {
+            throw new PelInvalidArgumentException('Argument "%s" must be a PelEntry.', $e);
+        }
+    }
+
+    /**
+     * Unset a given tag in this IFD.
+     *
+     * This methods is part of the ArrayAccess SPL interface for
+     * overriding array access of objects, it allows you to delete
+     * entries in the IFD by doing:
+     *
+     * <code>
+     * unset($ifd[PelTag::EXPOSURE_BIAS_VALUE])
+     * </code>
+     *
+     * @param PelTag $tag
+     *            the offset to delete.
+     */
+    public function offsetUnset($tag)
+    {
+        unset($this->entries[$tag]);
+    }
+
+    /**
+     * Retrieve an entry.
+     *
+     * @param PelTag $tag
+     *            the tag identifying the entry.
+     *
+     * @return PelEntry the entry associated with the tag, or null if no
+     *         such entry exists.
+     */
+    public function getEntry($tag)
+    {
+        if (isset($this->entries[$tag])) {
+            return $this->entries[$tag];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns all entries contained in this IFD.
+     *
+     * @return array an array of {@link PelEntry} objects, or rather
+     *         descendant classes. The array has {@link PelTag}s as keys
+     *         and the entries as values.
+     *
+     * @see getEntry
+     * @see getIterator
+     */
+    public function getEntries()
+    {
+        return $this->entries;
+    }
+
+    /**
+     * Return an iterator for all entries contained in this IFD.
+     *
+     * Used with foreach as in
+     *
+     * <code>
+     * foreach ($ifd as $tag => $entry) {
+     * // $tag is now a PelTag and $entry is a PelEntry object.
+     * }
+     * </code>
+     *
+     * @return Iterator an iterator using the {@link PelTag tags} as
+     *         keys and the entries as values.
+     */
+    public function getIterator()
+    {
+        return new \ArrayIterator($this->entries);
+    }
+
+    /**
+     * Returns available thumbnail data.
+     *
+     * @return string the bytes in the thumbnail, if any. If the IFD
+     *         does not contain any thumbnail data, the empty string is
+     *         returned.
+     *
+     * @todo Throw an exception instead when no data is available?
+     *
+     * @todo Return the $this->thumb_data object instead of the bytes?
+     */
+    public function getThumbnailData()
+    {
+        if ($this->thumb_data !== null) {
+            return $this->thumb_data->getBytes();
+        } else {
+            return '';
+        }
+    }
+
+    /**
+     * Make this directory point to a new directory.
+     *
+     * @param PelIfd $i
+     *            the IFD that this directory will point to.
+     */
+    public function setNextIfd(PelIfd $i)
+    {
+        $this->next = $i;
+    }
+
+    /**
+     * Return the IFD pointed to by this directory.
+     *
+     * @return PelIfd the next IFD, following this IFD. If this is the
+     *         last IFD, null is returned.
+     */
+    public function getNextIfd()
+    {
+        return $this->next;
+    }
+
+    /**
+     * Check if this is the last IFD.
+     *
+     * @return boolean true if there are no following IFD, false
+     *         otherwise.
+     */
+    public function isLastIfd()
+    {
+        return $this->next === null;
+    }
+
+    /**
+     * Add a sub-IFD.
+     *
+     * Any previous sub-IFD of the same type will be overwritten.
+     *
+     * @param PelIfd $sub
+     *            the sub IFD. The type of must be one of {@link
+     *            PelIfd::EXIF}, {@link PelIfd::GPS}, or {@link
+     *            PelIfd::INTEROPERABILITY}.
+     */
+    public function addSubIfd(PelIfd $sub)
+    {
+        $this->sub[$sub->type] = $sub;
+    }
+
+    /**
+     * Return a sub IFD.
+     *
+     * @param int $type
+     *            the type of the sub IFD. This must be one of {@link
+     *            PelIfd::EXIF}, {@link PelIfd::GPS}, or {@link
+     *            PelIfd::INTEROPERABILITY}.
+     *
+     * @return PelIfd the IFD associated with the type, or null if that
+     *         sub IFD does not exist.
+     */
+    public function getSubIfd($type)
+    {
+        if (isset($this->sub[$type])) {
+            return $this->sub[$type];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get all sub IFDs.
+     *
+     * @return array an associative array with (IFD-type, {@link
+     *         PelIfd}) pairs.
+     */
+    public function getSubIfds()
+    {
+        return $this->sub;
+    }
+
+    /**
+     * Turn this directory into bytes.
+     *
+     * This directory will be turned into a byte string, with the
+     * specified byte order. The offsets will be calculated from the
+     * offset given.
+     *
+     * @param int $offset
+     *            the offset of the first byte of this directory.
+     *
+     * @param PelByteOrder $order
+     *            the byte order that should be used when
+     *            turning integers into bytes. This should be one of {@link
+     *            PelConvert::LITTLE_ENDIAN} and {@link PelConvert::BIG_ENDIAN}.
+     */
+    public function getBytes($offset, $order)
+    {
+        $bytes = '';
+        $extra_bytes = '';
+
+        Pel::debug('Bytes from IDF will start at offset %d within Exif data', $offset);
+
+        $n = count($this->entries) + count($this->sub);
+        if ($this->thumb_data !== null) {
+            /*
+             * We need two extra entries for the thumbnail offset and
+             * length.
+             */
+            $n += 2;
+        }
+
+        $bytes .= PelConvert::shortToBytes($n, $order);
+
+        /*
+         * Initialize offset of extra data. This included the bytes
+         * preceding this IFD, the bytes needed for the count of entries,
+         * the entries themselves (and sub entries), the extra data in the
+         * entries, and the IFD link.
+         */
+        $end = $offset + 2 + 12 * $n + 4;
+
+        foreach ($this->entries as $tag => $entry) {
+            /* Each entry is 12 bytes long. */
+            $bytes .= PelConvert::shortToBytes($entry->getTag(), $order);
+            $bytes .= PelConvert::shortToBytes($entry->getFormat(), $order);
+            $bytes .= PelConvert::longToBytes($entry->getComponents(), $order);
+
+            /*
+             * Size? If bigger than 4 bytes, the actual data is not in
+             * the entry but somewhere else.
+             */
+            $data = $entry->getBytes($order);
+            $s = strlen($data);
+            if ($s > 4) {
+                Pel::debug('Data size %d too big, storing at offset %d instead.', $s, $end);
+                $bytes .= PelConvert::longToBytes($end, $order);
+                $extra_bytes .= $data;
+                $end += $s;
+            } else {
+                Pel::debug('Data size %d fits.', $s);
+                /*
+                 * Copy data directly, pad with NULL bytes as necessary to
+                 * fill out the four bytes available.
+                 */
+                $bytes .= $data . str_repeat(chr(0), 4 - $s);
+            }
+        }
+
+        if ($this->thumb_data !== null) {
+            Pel::debug('Appending %d bytes of thumbnail data at %d', $this->thumb_data->getSize(), $end);
+            // TODO: make PelEntry a class that can be constructed with
+            // arguments corresponding to the newt four lines.
+            $bytes .= PelConvert::shortToBytes(PelTag::JPEG_INTERCHANGE_FORMAT_LENGTH, $order);
+            $bytes .= PelConvert::shortToBytes(PelFormat::LONG, $order);
+            $bytes .= PelConvert::longToBytes(1, $order);
+            $bytes .= PelConvert::longToBytes($this->thumb_data->getSize(), $order);
+
+            $bytes .= PelConvert::shortToBytes(PelTag::JPEG_INTERCHANGE_FORMAT, $order);
+            $bytes .= PelConvert::shortToBytes(PelFormat::LONG, $order);
+            $bytes .= PelConvert::longToBytes(1, $order);
+            $bytes .= PelConvert::longToBytes($end, $order);
+
+            $extra_bytes .= $this->thumb_data->getBytes();
+            $end += $this->thumb_data->getSize();
+        }
+
+        /* Find bytes from sub IFDs. */
+        $sub_bytes = '';
+        foreach ($this->sub as $type => $sub) {
+            if ($type == PelIfd::EXIF) {
+                $tag = PelTag::EXIF_IFD_POINTER;
+            } elseif ($type == PelIfd::GPS) {
+                $tag = PelTag::GPS_INFO_IFD_POINTER;
+            } elseif ($type == PelIfd::INTEROPERABILITY) {
+                $tag = PelTag::INTEROPERABILITY_IFD_POINTER;
+            } else {
+                // PelConvert::BIG_ENDIAN is the default used by PelConvert
+                $tag = PelConvert::BIG_ENDIAN;
+            }
+            /* Make an aditional entry with the pointer. */
+            $bytes .= PelConvert::shortToBytes($tag, $order);
+            /* Next the format, which is always unsigned long. */
+            $bytes .= PelConvert::shortToBytes(PelFormat::LONG, $order);
+            /* There is only one component. */
+            $bytes .= PelConvert::longToBytes(1, $order);
+
+            $data = $sub->getBytes($end, $order);
+            $s = strlen($data);
+            $sub_bytes .= $data;
+
+            $bytes .= PelConvert::longToBytes($end, $order);
+            $end += $s;
+        }
+
+        /* Make link to next IFD, if any */
+        if ($this->isLastIFD()) {
+            $link = 0;
+        } else {
+            $link = $end;
+        }
+
+        Pel::debug('Link to next IFD: %d', $link);
+
+        $bytes .= PelConvert::longtoBytes($link, $order);
+
+        $bytes .= $extra_bytes . $sub_bytes;
+
+        if (! $this->isLastIfd()) {
+            $bytes .= $this->next->getBytes($end, $order);
+        }
+        return $bytes;
+    }
+
+    /**
+     * Turn this directory into text.
+     *
+     * @return string information about the directory, mainly for
+     *         debugging.
+     */
+    public function __toString()
+    {
+        $str = Pel::fmt("Dumping IFD %s with %d entries...\n", $this->getName(), count($this->entries));
+
+        foreach ($this->entries as $entry) {
+            $str .= $entry->__toString();
+        }
+        $str .= Pel::fmt("Dumping %d sub IFDs...\n", count($this->sub));
+
+        foreach ($this->sub as $type => $ifd) {
+            $str .= $ifd->__toString();
+        }
+        if ($this->next !== null) {
+            $str .= $this->next->__toString();
+        }
+        return $str;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelIfdException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelIfdException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e50d1e5b76318095cb720dccc658d236d6227594
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelIfdException.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif IFDs.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Exception indicating a general problem with the IFD.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelIfdException extends PelException
+{
+    // do nothing
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelInvalidArgumentException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelInvalidArgumentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..e72759d94eb95a1d951ac753435ef39cc5844c02
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelInvalidArgumentException.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+use lsolesen\pel\PelException;
+
+/**
+ * Standard PEL exception.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Exception throw if an invalid argument is passed.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelInvalidArgumentException extends PelException
+{
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelInvalidDataException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelInvalidDataException.php
new file mode 100644
index 0000000000000000000000000000000000000000..66a48258bd62abc7d5f0b1590d972315feb46822
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelInvalidDataException.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+use lsolesen\pel\PelException;
+
+/**
+ * Standard PEL exception.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Exception throw if invalid data is found.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelInvalidDataException extends PelException
+{
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpeg.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpeg.php
new file mode 100644
index 0000000000000000000000000000000000000000..c12e71cfc042a3206f55d42773333836edcc5301
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpeg.php
@@ -0,0 +1,663 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+namespace lsolesen\pel;
+
+/**
+ * Class for handling JPEG data.
+ *
+ * The {@link PelJpeg} class defined here provides an abstraction for
+ * dealing with a JPEG file. The file will be contain a number of
+ * sections containing some {@link PelJpegContent content} identified
+ * by a {@link PelJpegMarker marker}.
+ *
+ * The {@link getExif()} method is used get hold of the {@link
+ * PelJpegMarker::APP1 APP1} section which stores Exif data. So if
+ * the name of the JPEG file is stored in $filename, then one would
+ * get hold of the Exif data by saying:
+ *
+ * <code>
+ * $jpeg = new PelJpeg($filename);
+ * $exif = $jpeg->getExif();
+ * $tiff = $exif->getTiff();
+ * $ifd0 = $tiff->getIfd();
+ * $exif = $ifd0->getSubIfd(PelIfd::EXIF);
+ * $ifd1 = $ifd0->getNextIfd();
+ * </code>
+ *
+ * The $idf0 and $ifd1 variables will then be two {@link PelTiff TIFF}
+ * {@link PelIfd Image File Directories}, in which the data is stored
+ * under the keys found in {@link PelTag}.
+ *
+ * Should one have some image data (in the form of a {@link
+ * PelDataWindow}) of an unknown type, then the {@link
+ * PelJpeg::isValid()} function is handy: it will quickly test if the
+ * data could be valid JPEG data. The {@link PelTiff::isValid()}
+ * function does the same for TIFF images.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelJpeg
+{
+
+    /**
+     * The sections in the JPEG data.
+     *
+     * A JPEG file is built up as a sequence of sections, each section
+     * is identified with a {@link PelJpegMarker}. Some sections can
+     * occur more than once in the JPEG stream (the {@link
+     * PelJpegMarker::DQT DQT} and {@link PelJpegMarker::DHT DTH}
+     * markers for example) and so this is an array of ({@link
+     * PelJpegMarker}, {@link PelJpegContent}) pairs.
+     *
+     * The content can be either generic {@link PelJpegContent JPEG
+     * content} or {@link PelExif Exif data}.
+     *
+     * @var array
+     */
+    private $sections = array();
+
+    /**
+     * The JPEG image data.
+     *
+     * @var PelDataWindow
+     */
+    private $jpeg_data = null;
+
+    /**
+     * Construct a new JPEG object.
+     *
+     * The new object will be empty unless an argument is given from
+     * which it can initialize itself. This can either be the filename
+     * of a JPEG image, a {@link PelDataWindow} object or a PHP image
+     * resource handle.
+     *
+     * New Exif data (in the form of a {@link PelExif} object) can be
+     * inserted with the {@link setExif()} method:
+     *
+     * <code>
+     * $jpeg = new PelJpeg($data);
+     * // Create container for the Exif information:
+     * $exif = new PelExif();
+     * // Now Add a PelTiff object with a PelIfd object with one or more
+     * // PelEntry objects to $exif... Finally add $exif to $jpeg:
+     * $jpeg->setExif($exif);
+     * </code>
+     *
+     * @param
+     *            mixed the data that this JPEG. This can either be a
+     *            filename, a {@link PelDataWindow} object, or a PHP image resource
+     *            handle.
+     */
+    public function __construct($data = false)
+    {
+        if ($data === false) {
+            return;
+        }
+
+        if (is_string($data)) {
+            Pel::debug('Initializing PelJpeg object from %s', $data);
+            $this->loadFile($data);
+        } elseif ($data instanceof PelDataWindow) {
+            Pel::debug('Initializing PelJpeg object from PelDataWindow.');
+            $this->load($data);
+        } elseif (is_resource($data) && get_resource_type($data) == 'gd') {
+            Pel::debug('Initializing PelJpeg object from image resource.');
+            $this->load(new PelDataWindow($data));
+        } else {
+            throw new PelInvalidArgumentException('Bad type for $data: %s', gettype($data));
+        }
+    }
+
+    /**
+     * JPEG sections start with 0xFF. The first byte that is not
+     * 0xFF is a marker (hopefully).
+     *
+     * @param PelDataWindow $d
+     *
+     * @return integer
+     */
+    protected static function getJpgSectionStart($d)
+    {
+        for ($i = 0; $i < 7; $i ++) {
+            if ($d->getByte($i) != 0xFF) {
+                 break;
+            }
+        }
+        return $i;
+    }
+
+    /**
+     * Load data into a JPEG object.
+     *
+     * The data supplied will be parsed and turned into an object
+     * structure representing the image. This structure can then be
+     * manipulated and later turned back into an string of bytes.
+     *
+     * This methods can be called at any time after a JPEG object has
+     * been constructed, also after the {@link appendSection()} has been
+     * called to append custom sections. Loading several JPEG images
+     * into one object will accumulate the sections, but there will only
+     * be one {@link PelJpegMarker::SOS} section at any given time.
+     *
+     * @param
+     *            PelDataWindow the data that will be turned into JPEG
+     *            sections.
+     */
+    public function load(PelDataWindow $d)
+    {
+        Pel::debug('Parsing %d bytes...', $d->getSize());
+
+        /* JPEG data is stored in big-endian format. */
+        $d->setByteOrder(PelConvert::BIG_ENDIAN);
+
+        /*
+         * Run through the data to read the sections in the image. After
+         * each section is read, the start of the data window will be
+         * moved forward, and after the last section we'll terminate with
+         * no data left in the window.
+         */
+        while ($d->getSize() > 0) {
+            $i = $this->getJpgSectionStart($d);
+
+            $marker = $d->getByte($i);
+
+            if (!PelJpegMarker::isValid($marker)) {
+                throw new PelJpegInvalidMarkerException($marker, $i);
+            }
+
+            /*
+             * Move window so first byte becomes first byte in this
+             * section.
+             */
+            $d->setWindowStart($i + 1);
+
+            if ($marker == PelJpegMarker::SOI || $marker == PelJpegMarker::EOI) {
+                $content = new PelJpegContent(new PelDataWindow());
+                $this->appendSection($marker, $content);
+            } else {
+                /*
+                 * Read the length of the section. The length includes the
+                 * two bytes used to store the length.
+                 */
+                $len = $d->getShort(0) - 2;
+
+                Pel::debug('Found %s section of length %d', PelJpegMarker::getName($marker), $len);
+
+                /* Skip past the length. */
+                $d->setWindowStart(2);
+
+                if ($marker == PelJpegMarker::APP1) {
+                    try {
+                        $content = new PelExif();
+                        $content->load($d->getClone(0, $len));
+                    } catch (PelInvalidDataException $e) {
+                        /*
+                         * We store the data as normal JPEG content if it could
+                         * not be parsed as Exif data.
+                         */
+                        $content = new PelJpegContent($d->getClone(0, $len));
+                    }
+
+                    $this->appendSection($marker, $content);
+                    /* Skip past the data. */
+                    $d->setWindowStart($len);
+                } elseif ($marker == PelJpegMarker::COM) {
+                    $content = new PelJpegComment();
+                    $content->load($d->getClone(0, $len));
+                    $this->appendSection($marker, $content);
+                    $d->setWindowStart($len);
+                } else {
+                    $content = new PelJpegContent($d->getClone(0, $len));
+                    $this->appendSection($marker, $content);
+                    /* Skip past the data. */
+                    $d->setWindowStart($len);
+
+                    /* In case of SOS, image data will follow. */
+                    if ($marker == PelJpegMarker::SOS) {
+                        /*
+                         * Some images have some trailing (garbage?) following the
+                         * EOI marker. To handle this we seek backwards until we
+                         * find the EOI marker. Any trailing content is stored as
+                         * a PelJpegContent object.
+                         */
+
+                        $length = $d->getSize();
+                        while ($d->getByte($length - 2) != 0xFF || $d->getByte($length - 1) != PelJpegMarker::EOI) {
+                            $length --;
+                        }
+
+                        $this->jpeg_data = $d->getClone(0, $length - 2);
+                        Pel::debug('JPEG data: ' . $this->jpeg_data->__toString());
+
+                        /* Append the EOI. */
+                        $this->appendSection(PelJpegMarker::EOI, new PelJpegContent(new PelDataWindow()));
+
+                        /* Now check to see if there are any trailing data. */
+                        if ($length != $d->getSize()) {
+                            Pel::maybeThrow(new PelException('Found trailing content ' . 'after EOI: %d bytes', $d->getSize() - $length));
+                            $content = new PelJpegContent($d->getClone($length));
+                            /*
+                             * We don't have a proper JPEG marker for trailing
+                             * garbage, so we just use 0x00...
+                             */
+                            $this->appendSection(0x00, $content);
+                        }
+
+                        /* Done with the loop. */
+                        break;
+                    }
+                }
+            }
+        } /* while ($d->getSize() > 0) */
+    }
+
+    /**
+     * Load data from a file into a JPEG object.
+     *
+     * @param
+     *            string the filename. This must be a readable file.
+     */
+    public function loadFile($filename)
+    {
+        $this->load(new PelDataWindow(file_get_contents($filename)));
+    }
+
+    /**
+     * Set Exif data.
+     *
+     * Use this to set the Exif data in the image. This will overwrite
+     * any old Exif information in the image.
+     *
+     * @param
+     *            PelExif the Exif data.
+     */
+    public function setExif(PelExif $exif)
+    {
+        $app0_offset = 1;
+        $app1_offset = - 1;
+
+        /* Search through all sections looking for APP0 or APP1. */
+        $sections_count = count($this->sections);
+        for ($i = 0; $i < $sections_count; $i ++) {
+            if (! empty($this->sections[$i][0])) {
+                if ($this->sections[$i][0] == PelJpegMarker::APP0) {
+                    $app0_offset = $i;
+                } elseif ($this->sections[$i][0] == PelJpegMarker::APP1) {
+                    $app1_offset = $i;
+                    break;
+                }
+            }
+        }
+
+        /*
+         * Store the Exif data at the appropriate place, either where the
+         * old Exif data was stored ($app1_offset) or right after APP0
+         * ($app0_offset+1).
+         */
+        if ($app1_offset > 0) {
+            $this->sections[$app1_offset][1] = $exif;
+        } else {
+            $this->insertSection(PelJpegMarker::APP1, $exif, $app0_offset + 1);
+        }
+    }
+
+    /**
+     * Set ICC data.
+     *
+     * Use this to set the ICC data in the image. This will overwrite
+     * any old ICC information in the image.
+     *
+     * @param
+     *            PelJpegContent the ICC data.
+     */
+    public function setICC(PelJpegContent $icc)
+    {
+        $app1_offset = 1;
+        $app2_offset = - 1;
+
+        /* Search through all sections looking for APP0 or APP1. */
+        $count_sections = count($this->sections);
+        for ($i = 0; $i < $count_sections; $i ++) {
+            if (! empty($this->sections[$i][0])) {
+                if ($this->sections[$i][0] == PelJpegMarker::APP1) {
+                    $app1_offset = $i;
+                } elseif ($this->sections[$i][0] == PelJpegMarker::APP2) {
+                    $app2_offset = $i;
+                    break;
+                }
+            }
+        }
+
+        /*
+         * Store the Exif data at the appropriate place, either where the
+         * old Exif data was stored ($app1_offset) or right after APP0
+         * ($app0_offset+1).
+         */
+        if ($app2_offset > 0) {
+            $this->sections[$app1_offset][1] = $icc;
+        } else {
+            $this->insertSection(PelJpegMarker::APP2, $icc, $app1_offset + 1);
+        }
+    }
+
+    /**
+     * Get Exif data.
+     *
+     * Use this to get the @{link PelExif Exif data} stored.
+     *
+     * @return PelExif the Exif data found or null if the image has no
+     *         Exif data.
+     */
+    public function getExif()
+    {
+        $exif = $this->getSection(PelJpegMarker::APP1);
+        if ($exif instanceof PelExif) {
+            return $exif;
+        }
+        return null;
+    }
+
+    /**
+     * Get ICC data.
+     *
+     * Use this to get the @{link PelJpegContent ICC data} stored.
+     *
+     * @return PelJpegContent the ICC data found or null if the image has no
+     *         ICC data.
+     */
+    public function getICC()
+    {
+        $icc = $this->getSection(PelJpegMarker::APP2);
+        if ($icc instanceof PelJpegContent) {
+            return $icc;
+        }
+        return null;
+    }
+
+    /**
+     * Clear any Exif data.
+     *
+     * This method will only clear the first @{link PelJpegMarker::APP1}
+     * section found (there should normally be just one).
+     */
+    public function clearExif()
+    {
+        $sections_count = count($this->sections);
+        for ($i = 0; $i < $sections_count; $i ++) {
+            if ($this->sections[$i][0] == PelJpegMarker::APP1) {
+                unset($this->sections[$i]);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Append a new section.
+     *
+     * Used only when loading an image. If it used again later, then the
+     * section will end up after the @{link PelJpegMarker::EOI EOI
+     * marker} and will probably not be useful.
+     *
+     * Please use @{link setExif()} instead if you intend to add Exif
+     * information to an image as that function will know the right
+     * place to insert the data.
+     *
+     * @param
+     *            PelJpegMarker the marker identifying the new section.
+     *
+     * @param
+     *            PelJpegContent the content of the new section.
+     */
+    public function appendSection($marker, PelJpegContent $content)
+    {
+        $this->sections[] = array(
+            $marker,
+            $content
+        );
+    }
+
+    /**
+     * Insert a new section.
+     *
+     * Please use @{link setExif()} instead if you intend to add Exif
+     * information to an image as that function will know the right
+     * place to insert the data.
+     *
+     * @param
+     *            PelJpegMarker the marker for the new section.
+     *
+     * @param
+     *            PelJpegContent the content of the new section.
+     *
+     * @param
+     *            int the offset where the new section will be inserted ---
+     *            use 0 to insert it at the very beginning, use 1 to insert it
+     *            between sections 1 and 2, etc.
+     */
+    public function insertSection($marker, PelJpegContent $content, $offset)
+    {
+        array_splice($this->sections, $offset, 0, array(
+            array(
+                $marker,
+                $content
+            )
+        ));
+    }
+
+    /**
+     * Get a section corresponding to a particular marker.
+     *
+     * Please use the {@link getExif()} if you just need the Exif data.
+     *
+     * This will search through the sections of this JPEG object,
+     * looking for a section identified with the specified {@link
+     * PelJpegMarker marker}. The {@link PelJpegContent content} will
+     * then be returned. The optional argument can be used to skip over
+     * some of the sections. So if one is looking for the, say, third
+     * {@link PelJpegMarker::DHT DHT} section one would do:
+     *
+     * <code>
+     * $dht3 = $jpeg->getSection(PelJpegMarker::DHT, 2);
+     * </code>
+     *
+     * @param
+     *            PelJpegMarker the marker identifying the section.
+     *
+     * @param
+     *            int the number of sections to be skipped. This must be a
+     *            non-negative integer.
+     *
+     * @return PelJpegContent the content found, or null if there is no
+     *         content available.
+     */
+    public function getSection($marker, $skip = 0)
+    {
+        foreach ($this->sections as $s) {
+            if ($s[0] == $marker) {
+                if ($skip > 0) {
+                    $skip --;
+                } else {
+                    return $s[1];
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get all sections.
+     *
+     * @return array an array of ({@link PelJpegMarker}, {@link
+     *         PelJpegContent}) pairs. Each pair is an array with the {@link
+     *         PelJpegMarker} as the first element and the {@link
+     *         PelJpegContent} as the second element, so the return type is an
+     *         array of arrays.
+     *
+     *         So to loop through all the sections in a given JPEG image do
+     *         this:
+     *
+     *         <code>
+     *         foreach ($jpeg->getSections() as $section) {
+     *         $marker = $section[0];
+     *         $content = $section[1];
+     *         // Use $marker and $content here.
+     *         }
+     *         </code>
+     *
+     *         instead of this:
+     *
+     *         <code>
+     *         foreach ($jpeg->getSections() as $marker => $content) {
+     *         // Does not work the way you would think...
+     *         }
+     *         </code>
+     *
+     *         The problem is that there could be several sections with the same
+     *         marker, and thus a simple associative array does not suffice.
+     */
+    public function getSections()
+    {
+        return $this->sections;
+    }
+
+    /**
+     * Turn this JPEG object into bytes.
+     *
+     * The bytes returned by this method is ready to be stored in a file
+     * as a valid JPEG image. Use the {@link saveFile()} convenience
+     * method to do this.
+     *
+     * @return string bytes representing this JPEG object, including all
+     *         its sections and their associated data.
+     */
+    public function getBytes()
+    {
+        $bytes = '';
+
+        foreach ($this->sections as $section) {
+            $m = $section[0];
+            $c = $section[1];
+
+            /* Write the marker */
+            $bytes .= "\xFF" . PelJpegMarker::getBytes($m);
+            /* Skip over empty markers. */
+            if ($m == PelJpegMarker::SOI || $m == PelJpegMarker::EOI) {
+                continue;
+            }
+
+            $data = $c->getBytes();
+            $size = strlen($data) + 2;
+
+            $bytes .= PelConvert::shortToBytes($size, PelConvert::BIG_ENDIAN);
+            $bytes .= $data;
+
+            /* In case of SOS, we need to write the JPEG data. */
+            if ($m == PelJpegMarker::SOS) {
+                $bytes .= $this->jpeg_data->getBytes();
+            }
+        }
+
+        return $bytes;
+    }
+
+    /**
+     * Save the JPEG object as a JPEG image in a file.
+     *
+     * @param
+     *            string the filename to save in. An existing file with the
+     *            same name will be overwritten!
+     *
+     * @return integer|FALSE The number of bytes that were written to the
+     *         file, or FALSE on failure.
+     */
+    public function saveFile($filename)
+    {
+        return file_put_contents($filename, $this->getBytes());
+    }
+
+    /**
+     * Make a string representation of this JPEG object.
+     *
+     * This is mainly usefull for debugging. It will show the structure
+     * of the image, and its sections.
+     *
+     * @return string debugging information about this JPEG object.
+     */
+    public function __toString()
+    {
+        $str = Pel::tra("Dumping JPEG data...\n");
+        $count_sections = count($this->sections);
+        for ($i = 0; $i < $count_sections; $i ++) {
+            $m = $this->sections[$i][0];
+            $c = $this->sections[$i][1];
+            $str .= Pel::fmt("Section %d (marker 0x%02X - %s):\n", $i, $m, PelJpegMarker::getName($m));
+            $str .= Pel::fmt("  Description: %s\n", PelJpegMarker::getDescription($m));
+
+            if ($m == PelJpegMarker::SOI || $m == PelJpegMarker::EOI) {
+                continue;
+            }
+
+            if ($c instanceof PelExif) {
+                $str .= Pel::tra("  Content    : Exif data\n");
+                $str .= $c->__toString() . "\n";
+            } elseif ($c instanceof PelJpegComment) {
+                $str .= Pel::fmt("  Content    : %s\n", $c->getValue());
+            } else {
+                $str .= Pel::tra("  Content    : Unknown\n");
+            }
+        }
+
+        return $str;
+    }
+
+    /**
+     * Test data to see if it could be a valid JPEG image.
+     *
+     * The function will only look at the first few bytes of the data,
+     * and try to determine if it could be a valid JPEG image based on
+     * those bytes. This means that the check is more like a heuristic
+     * than a rigorous check.
+     *
+     * @param
+     *            PelDataWindow the bytes that will be checked.
+     *
+     * @return boolean true if the bytes look like the beginning of a
+     *         JPEG image, false otherwise.
+     *
+     * @see PelTiff::isValid()
+     */
+    public static function isValid(PelDataWindow $d)
+    {
+        /* JPEG data is stored in big-endian format. */
+        $d->setByteOrder(PelConvert::BIG_ENDIAN);
+
+        $i = self::getJpgSectionStart($d);
+
+        return $d->getByte($i) == PelJpegMarker::SOI;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegComment.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegComment.php
new file mode 100644
index 0000000000000000000000000000000000000000..6d04d1a95f69bfd227027baf383c3b50761177a6
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegComment.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2005, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Class for dealing with JPEG comments.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class representing JPEG comments.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelJpegComment extends PelJpegContent
+{
+
+    /**
+     * The comment.
+     *
+     * @var string
+     */
+    private $comment = '';
+
+    /**
+     * Construct a new JPEG comment.
+     *
+     * The new comment will contain the string given.
+     *
+     * @param string $comment
+     */
+    public function __construct($comment = '')
+    {
+        $this->comment = $comment;
+    }
+
+    /**
+     * Load and parse data.
+     *
+     * This will load the comment from the data window passed.
+     *
+     * @param PelDataWindow $d
+     */
+    public function load(PelDataWindow $d)
+    {
+        $this->comment = $d->getBytes();
+    }
+
+    /**
+     * Update the value with a new comment.
+     *
+     * Any old comment will be overwritten.
+     *
+     * @param string $comment
+     *            the new comment.
+     */
+    public function setValue($comment)
+    {
+        $this->comment = $comment;
+    }
+
+    /**
+     * Get the comment.
+     *
+     * @return string the comment.
+     */
+    public function getValue()
+    {
+        return $this->comment;
+    }
+
+    /**
+     * Turn this comment into bytes.
+     *
+     * @return string bytes representing this comment.
+     */
+    public function getBytes()
+    {
+        return $this->comment;
+    }
+
+    /**
+     * Return a string representation of this object.
+     *
+     * @return string the same as {@link getValue()}.
+     */
+    public function __toString()
+    {
+        return $this->getValue();
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegContent.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegContent.php
new file mode 100644
index 0000000000000000000000000000000000000000..c2822771f1c6484ec96981ca7125febaf2c508f7
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegContent.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+use \lsolesen\pel\PelDataWindow;
+
+/**
+ * Class representing content in a JPEG file.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class representing content in a JPEG file.
+ *
+ * A JPEG file consists of a sequence of each of which has an
+ * associated {@link PelJpegMarker marker} and some content. This
+ * class represents the content, and this basic type is just a simple
+ * holder of such content, represented by a {@link PelDataWindow}
+ * object. The {@link PelExif} class is an example of more
+ * specialized JPEG content.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelJpegContent
+{
+
+    private $data = null;
+
+    /**
+     * Make a new piece of JPEG content.
+     *
+     * @param PelDataWindow $data
+     *            the content.
+     */
+    public function __construct(PelDataWindow $data)
+    {
+        $this->data = $data;
+    }
+
+    /**
+     * Return the bytes of the content.
+     *
+     * @return string bytes representing this JPEG content. These bytes
+     *         will match the bytes given to {@link __construct the
+     *         constructor}.
+     */
+    public function getBytes()
+    {
+        return $this->data->getBytes();
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegInvalidMarkerException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegInvalidMarkerException.php
new file mode 100644
index 0000000000000000000000000000000000000000..5eb7637f8cb694c4240a70784d7d285f905beca8
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegInvalidMarkerException.php
@@ -0,0 +1,55 @@
+<?php
+/*
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Exception thrown when an invalid marker is found.
+ *
+ * This exception is thrown when PEL expects to find a {@link
+ * PelJpegMarker} and instead finds a byte that isn't a known marker.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License (GPL)
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelJpegInvalidMarkerException extends PelException
+{
+
+    /**
+     * Construct a new invalid marker exception.
+     * The exception will contain a message describing the error,
+     * including the byte found and the offset of the offending byte.
+     *
+     * @param int $marker
+     *            the byte found.
+     *
+     * @param int $offset
+     *            the offset in the data.
+     */
+    public function __construct($marker, $offset)
+    {
+        parent::__construct('Invalid marker found at offset %d: 0x%2X', $offset, $marker);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegMarker.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegMarker.php
new file mode 100644
index 0000000000000000000000000000000000000000..4d1bd33ce4333ddefb4568e2e420b01a9e37106b
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelJpegMarker.php
@@ -0,0 +1,542 @@
+<?php
+
+/*
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2006 Martin Geisler.
+ * Copyright (C) 2017 Johannes Weberhofer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with JPEG markers.
+ *
+ * This class defines the constants to be used whenever one refers to
+ * a JPEG marker. All the methods defined are static, and they all
+ * operate on one argument which should be one of the class constants.
+ * They will all be denoted by PelJpegMarker in the documentation.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @author Johannes Weberhofer <jweberhofer@weberhofer.at>
+ *
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+class PelJpegMarker
+{
+
+    /**
+     * Encoding (baseline)
+     */
+    const SOF0 = 0xC0;
+
+    /**
+     * Encoding (extended sequential)
+     */
+    const SOF1 = 0xC1;
+
+    /**
+     * Encoding (progressive)
+     */
+    const SOF2 = 0xC2;
+
+    /**
+     * Encoding (lossless)
+     */
+    const SOF3 = 0xC3;
+
+    /**
+     * Define Huffman table
+     */
+    const DHT = 0xC4;
+
+    /**
+     * Encoding (differential sequential)
+     */
+    const SOF5 = 0xC5;
+
+    /**
+     * Encoding (differential progressive)
+     */
+    const SOF6 = 0xC6;
+
+    /**
+     * Encoding (differential lossless)
+     */
+    const SOF7 = 0xC7;
+
+    /**
+     * Extension
+     */
+    const JPG = 0xC8;
+
+    /**
+     * Encoding (extended sequential, arithmetic)
+     */
+    const SOF9 = 0xC9;
+
+    /**
+     * Encoding (progressive, arithmetic)
+     */
+    const SOF10 = 0xCA;
+
+    /**
+     * Encoding (lossless, arithmetic)
+     */
+    const SOF11 = 0xCB;
+
+    /**
+     * Define arithmetic coding conditioning
+     */
+    const DAC = 0xCC;
+
+    /**
+     * Encoding (differential sequential, arithmetic)
+     */
+    const SOF13 = 0xCD;
+
+    /**
+     * Encoding (differential progressive, arithmetic)
+     */
+    const SOF14 = 0xCE;
+
+    /**
+     * Encoding (differential lossless, arithmetic)
+     */
+    const SOF15 = 0xCF;
+
+    /**
+     * Restart 0
+     */
+    const RST0 = 0xD0;
+
+    /**
+     * Restart 1
+     */
+    const RST1 = 0xD1;
+
+    /**
+     * Restart 2
+     */
+    const RST2 = 0xD2;
+
+    /**
+     * Restart 3
+     */
+    const RST3 = 0xD3;
+
+    /**
+     * Restart 4
+     */
+    const RST4 = 0xD4;
+
+    /**
+     * Restart 5
+     */
+    const RST5 = 0xD5;
+
+    /**
+     * Restart 6
+     */
+    const RST6 = 0xD6;
+
+    /**
+     * Restart 7
+     */
+    const RST7 = 0xD7;
+
+    /**
+     * Start of image
+     */
+    const SOI = 0xD8;
+
+    /**
+     * End of image
+     */
+    const EOI = 0xD9;
+
+    /**
+     * Start of scan
+     */
+    const SOS = 0xDA;
+
+    /**
+     * Define quantization table
+     */
+    const DQT = 0xDB;
+
+    /**
+     * Define number of lines
+     */
+    const DNL = 0xDC;
+
+    /**
+     * Define restart interval
+     */
+    const DRI = 0xDD;
+
+    /**
+     * Define hierarchical progression
+     */
+    const DHP = 0xDE;
+
+    /**
+     * Expand reference component
+     */
+    const EXP = 0xDF;
+
+    /**
+     * Application segment 0
+     */
+    const APP0 = 0xE0;
+
+    /**
+     * Application segment 1
+     *
+     * When a JPEG image contains Exif data, the data will normally be
+     * stored in this section and a call to {@link PelJpeg::getExif()}
+     * will return a {@link PelExif} object representing it.
+     */
+    const APP1 = 0xE1;
+
+    /**
+     * Application segment 2
+     */
+    const APP2 = 0xE2;
+
+    /**
+     * Application segment 3
+     */
+    const APP3 = 0xE3;
+
+    /**
+     * Application segment 4
+     */
+    const APP4 = 0xE4;
+
+    /**
+     * Application segment 5
+     */
+    const APP5 = 0xE5;
+
+    /**
+     * Application segment 6
+     */
+    const APP6 = 0xE6;
+
+    /**
+     * Application segment 7
+     */
+    const APP7 = 0xE7;
+
+    /**
+     * Application segment 8
+     */
+    const APP8 = 0xE8;
+
+    /**
+     * Application segment 9
+     */
+    const APP9 = 0xE9;
+
+    /**
+     * Application segment 10
+     */
+    const APP10 = 0xEA;
+
+    /**
+     * Application segment 11
+     */
+    const APP11 = 0xEB;
+
+    /**
+     * Application segment 12
+     */
+    const APP12 = 0xEC;
+
+    /**
+     * Application segment 13
+     */
+    const APP13 = 0xED;
+
+    /**
+     * Application segment 14
+     */
+    const APP14 = 0xEE;
+
+    /**
+     * Application segment 15
+     */
+    const APP15 = 0xEF;
+
+    /**
+     * Extension 0
+     */
+    const JPG0 = 0xF0;
+
+    /**
+     * Extension 1
+     */
+    const JPG1 = 0xF1;
+
+    /**
+     * Extension 2
+     */
+    const JPG2 = 0xF2;
+
+    /**
+     * Extension 3
+     */
+    const JPG3 = 0xF3;
+
+    /**
+     * Extension 4
+     */
+    const JPG4 = 0xF4;
+
+    /**
+     * Extension 5
+     */
+    const JPG5 = 0xF5;
+
+    /**
+     * Extension 6
+     */
+    const JPG6 = 0xF6;
+
+    /**
+     * Extension 7
+     */
+    const JPG7 = 0xF7;
+
+    /**
+     * Extension 8
+     */
+    const JPG8 = 0xF8;
+
+    /**
+     * Extension 9
+     */
+    const JPG9 = 0xF9;
+
+    /**
+     * Extension 10
+     */
+    const JPG10 = 0xFA;
+
+    /**
+     * Extension 11
+     */
+    const JPG11 = 0xFB;
+
+    /**
+     * Extension 12
+     */
+    const JPG12 = 0xFC;
+
+    /**
+     * Extension 13
+     */
+    const JPG13 = 0xFD;
+
+    /**
+     * Comment
+     */
+    const COM = 0xFE;
+
+    /**
+     * Values for marker's short names
+     */
+    protected static $jpegMarkerShort = array(
+        self::SOF0 => 'SOF0',
+        self::SOF1 => 'SOF1',
+        self::SOF2 => 'SOF2',
+        self::SOF3 => 'SOF3',
+        self::SOF5 => 'SOF5',
+        self::SOF6 => 'SOF6',
+        self::SOF7 => 'SOF7',
+        self::SOF9 => 'SOF9',
+        self::SOF10 => 'SOF10',
+        self::SOF11 => 'SOF11',
+        self::SOF13 => 'SOF13',
+        self::SOF14 => 'SOF14',
+        self::SOF15 => 'SOF15',
+        self::SOI => 'SOI',
+        self::EOI => 'EOI',
+        self::SOS => 'SOS',
+        self::COM => 'COM',
+        self::DHT => 'DHT',
+        self::JPG => 'JPG',
+        self::DAC => 'DAC',
+        self::RST0 => 'RST0',
+        self::RST1 => 'RST1',
+        self::RST2 => 'RST2',
+        self::RST3 => 'RST3',
+        self::RST4 => 'RST4',
+        self::RST5 => 'RST5',
+        self::RST6 => 'RST6',
+        self::RST7 => 'RST7',
+        self::DQT => 'DQT',
+        self::DNL => 'DNL',
+        self::DRI => 'DRI',
+        self::DHP => 'DHP',
+        self::EXP => 'EXP',
+        self::APP0 => 'APP0',
+        self::APP1 => 'APP1',
+        self::APP2 => 'APP2',
+        self::APP3 => 'APP3',
+        self::APP4 => 'APP4',
+        self::APP5 => 'APP5',
+        self::APP6 => 'APP6',
+        self::APP7 => 'APP7',
+        self::APP8 => 'APP8',
+        self::APP9 => 'APP9',
+        self::APP10 => 'APP10',
+        self::APP11 => 'APP11',
+        self::APP12 => 'APP12',
+        self::APP13 => 'APP13',
+        self::APP14 => 'APP14',
+        self::APP15 => 'APP15',
+        self::JPG0 => 'JPG0',
+        self::JPG1 => 'JPG1',
+        self::JPG2 => 'JPG2',
+        self::JPG3 => 'JPG3',
+        self::JPG4 => 'JPG4',
+        self::JPG5 => 'JPG5',
+        self::JPG6 => 'JPG6',
+        self::JPG7 => 'JPG7',
+        self::JPG8 => 'JPG8',
+        self::JPG9 => 'JPG9',
+        self::JPG10 => 'JPG10',
+        self::JPG11 => 'JPG11',
+        self::JPG12 => 'JPG12',
+        self::JPG13 => 'JPG13',
+        self::COM => 'COM'
+    );
+
+    /**
+     * Values for marker's descriptions names.
+     */
+    protected static $jpegMarkerDescriptions = array(
+        self::SOF0 => 'Encoding (baseline)',
+        self::SOF1 => 'Encoding (extended sequential)',
+        self::SOF2 => 'Encoding (progressive)',
+        self::SOF3 => 'Encoding (lossless)',
+        self::SOF5 => 'Encoding (differential sequential)',
+        self::SOF6 => 'Encoding (differential progressive)',
+        self::SOF7 => 'Encoding (differential lossless)',
+        self::SOF9 => 'Encoding (extended sequential, arithmetic)',
+        self::SOF10 => 'Encoding (progressive, arithmetic)',
+        self::SOF11 => 'Encoding (lossless, arithmetic)',
+        self::SOF13 => 'Encoding (differential sequential, arithmetic)',
+        self::SOF14 => 'Encoding (differential progressive, arithmetic)',
+        self::SOF15 => 'Encoding (differential lossless, arithmetic)',
+        self::SOI => 'Start of image',
+        self::EOI => 'End of image',
+        self::SOS => 'Start of scan',
+        self::COM => 'Comment',
+        self::DHT => 'Define Huffman table',
+        self::JPG => 'Extension',
+        self::DAC => 'Define arithmetic coding conditioning',
+        'RST' => 'Restart %d',
+        self::DQT => 'Define quantization table',
+        self::DNL => 'Define number of lines',
+        self::DRI => 'Define restart interval',
+        self::DHP => 'Define hierarchical progression',
+        self::EXP => 'Expand reference component',
+        'APP' => 'Application segment %d',
+        'JPG' => 'Extension %d',
+        self::COM => 'Comment'
+    );
+
+    /**
+     * Check if a byte is a valid JPEG marker.
+     * If the byte is recognized true is returned, otherwise false will be returned.
+     *
+     * @param integer $marker
+     *            the marker as defined in {@link PelJpegMarker}
+     *
+     * @return boolean
+     */
+    public static function isValid($marker)
+    {
+        return ($marker >= self::SOF0 && $marker <= self::COM);
+    }
+
+    /**
+     * Turn a JPEG marker into bytes.
+     * This will be a string with just a single byte since all JPEG markers are simply single bytes.
+     *
+     * @param integer $marker
+     *            the marker as defined in {@link PelJpegMarker}
+     *
+     * @return string
+     */
+    public static function getBytes($marker)
+    {
+        return chr($marker);
+    }
+
+    /**
+     * Return the short name for a marker, e.g., 'SOI' for the Start
+     * of Image marker.
+     *
+     * @param integer $marker
+     *            the marker as defined in {@link PelJpegMarker}
+     *
+     * @return string
+     */
+    public static function getName($marker)
+    {
+        if (array_key_exists($marker, self::$jpegMarkerShort)) {
+            return self::$jpegMarkerShort[$marker];
+        } else {
+            return Pel::fmt('Unknown marker: 0x%02X', $marker);
+        }
+    }
+
+    /**
+     * Returns a description of a JPEG marker.
+     *
+     * @param integer $marker
+     *            the marker as defined in {@link PelJpegMarker}
+     *
+     * @return string
+     */
+    public static function getDescription($marker)
+    {
+        if (array_key_exists($marker, self::$jpegMarkerShort)) {
+            if (array_key_exists($marker, self::$jpegMarkerDescriptions)) {
+                return self::$jpegMarkerDescriptions[$marker];
+            } else {
+                $splitted = preg_split(
+                    "/(\d+)/",
+                    self::$jpegMarkerShort[$marker],
+                    - 1,
+                    PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
+                if ((count($splitted) == 2) && array_key_exists($splitted[0], self::$jpegMarkerDescriptions)) {
+                    return Pel::fmt(self::$jpegMarkerDescriptions[$splitted[0]], $splitted[1]);
+                }
+            }
+        }
+        return Pel::fmt('Unknown marker: 0x%02X', $marker);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelOverflowException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelOverflowException.php
new file mode 100644
index 0000000000000000000000000000000000000000..634985b1aa35b9f7607b4ff47ad74ce1c2732d7c
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelOverflowException.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif entries.
+ *
+ * This file defines two exception classes and the abstract class
+ * {@link PelEntry} which provides the basic methods that all Exif
+ * entries will have. All Exif entries will be represented by
+ * descendants of the {@link PelEntry} class --- the class itself is
+ * abstract and so it cannot be instantiated.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Exception cast when numbers overflow.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelOverflowException extends PelException
+{
+
+    /**
+     * Construct a new overflow exception.
+     *
+     * @param int $v
+     *            the value that is out of range.
+     *
+     * @param int $min
+     *            the minimum allowed value.
+     *
+     * @param int $max
+     *            the maximum allowed value.
+     */
+    public function __construct($v, $min, $max)
+    {
+        parent::__construct('Value %.0f out of range [%.0f, %.0f]', $v, $min, $max);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelTag.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelTag.php
new file mode 100644
index 0000000000000000000000000000000000000000..04a957c11ef47f85efc9fc0f91f5c5b8fa256ec3
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelTag.php
@@ -0,0 +1,1723 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+    /**
+     * Namespace for functions operating on Exif tags.
+     *
+     * @author Martin Geisler <mgeisler@users.sourceforge.net>
+     * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+     *          License (GPL)
+     * @package PEL
+     */
+
+/**
+ * Class with static methods for Exif tags.
+ *
+ * This class defines the constants that represents the Exif tags
+ * known to PEL. They are supposed to be used whenever one needs to
+ * specify an Exif tag, and they will be denoted by the pseudo-type
+ * {@link PelTag} throughout the documentation.
+ *
+ * Please note that the constrains on the format and number of
+ * components given here are advisory only. To follow the Exif
+ * specification one should obey them, but there is nothing that
+ * prevents you from creating an {@link IMAGE_LENGTH} entry with two
+ * or more components, even though the standard says that there should
+ * be exactly one component.
+ *
+ * All the methods in this class are static and should be called with
+ * the Exif tag on which they should operate.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelTag
+{
+
+    /**
+     * Interoperability index.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 4.
+     */
+    const INTEROPERABILITY_INDEX = 0x0001;
+
+    /**
+     * Interoperability version.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: 4.
+     */
+    const INTEROPERABILITY_VERSION = 0x0002;
+
+    /**
+     * Image width.
+     *
+     * Format: {@link PelFormat::SHORT} or {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const IMAGE_WIDTH = 0x0100;
+
+    /**
+     * Image length.
+     *
+     * Format: {@link PelFormat::SHORT} or {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const IMAGE_LENGTH = 0x0101;
+
+    /**
+     * Number of bits per component.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 3.
+     */
+    const BITS_PER_SAMPLE = 0x0102;
+
+    /**
+     * Compression scheme.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const COMPRESSION = 0x0103;
+
+    /**
+     * Pixel composition.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const PHOTOMETRIC_INTERPRETATION = 0x0106;
+
+    /**
+     * Fill Order
+     *
+     * Format: Unknown.
+     *
+     * Components: Unknown.
+     */
+    const FILL_ORDER = 0x010A;
+
+    /**
+     * Document Name
+     *
+     * Format: {@link PelEntryAscii}.
+     *
+     * Components: any number.
+     */
+    const DOCUMENT_NAME = 0x010D;
+
+    /**
+     * Image Description
+     *
+     * Format: {@link PelEntryAscii}.
+     *
+     * Components: any number.
+     */
+    const IMAGE_DESCRIPTION = 0x010E;
+
+    /**
+     * Manufacturer
+     *
+     * Format: {@link PelEntryAscii}.
+     *
+     * Components: any number.
+     */
+    const MAKE = 0x010F;
+
+    /**
+     * Model
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const MODEL = 0x0110;
+
+    /**
+     * Strip Offsets
+     *
+     * Format: {@link PelFormat::SHORT} or {@link PelFormat::LONG}.
+     *
+     * Components: any number.
+     */
+    const STRIP_OFFSETS = 0x0111;
+
+    /**
+     * Orientation of image.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const ORIENTATION = 0x0112;
+
+    /**
+     * Number of components.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const SAMPLES_PER_PIXEL = 0x0115;
+
+    /**
+     * Rows per Strip
+     *
+     * Format: {@link PelFormat::SHORT} or {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const ROWS_PER_STRIP = 0x0116;
+
+    /**
+     * Strip Byte Count
+     *
+     * Format: {@link PelFormat::SHORT} or {@link PelFormat::LONG}.
+     *
+     * Components: any number.
+     */
+    const STRIP_BYTE_COUNTS = 0x0117;
+
+    /**
+     * Image resolution in width direction.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const X_RESOLUTION = 0x011A;
+
+    /**
+     * Image resolution in height direction.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const Y_RESOLUTION = 0x011B;
+
+    /**
+     * Image data arrangement.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const PLANAR_CONFIGURATION = 0x011C;
+
+    /**
+     * Unit of X and Y resolution.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const RESOLUTION_UNIT = 0x0128;
+
+    /**
+     * Transfer function.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 3.
+     */
+    const TRANSFER_FUNCTION = 0x012D;
+
+    /**
+     * Software used.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const SOFTWARE = 0x0131;
+
+    /**
+     * File change date and time.
+     *
+     * Format: {@link PelFormat::ASCII}, modelled by the {@link
+     * PelEntryTime} class.
+     *
+     * Components: 20.
+     */
+    const DATE_TIME = 0x0132;
+
+    /**
+     * Person who created the image.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const ARTIST = 0x013B;
+
+    /**
+     * White point chromaticity.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 2.
+     */
+    const WHITE_POINT = 0x013E;
+
+    /**
+     * Chromaticities of primaries.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 6.
+     */
+    const PRIMARY_CHROMATICITIES = 0x013F;
+
+    /**
+     * Transfer Range
+     *
+     * Format: Unknown.
+     *
+     * Components: Unknown.
+     */
+    const TRANSFER_RANGE = 0x0156;
+
+    /**
+     * JPEGProc
+     *
+     * Format: Unknown.
+     *
+     * Components: Unknown.
+     */
+    const JPEG_PROC = 0x0200;
+
+    /**
+     * Offset to JPEG SOI.
+     *
+     * Format: {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const JPEG_INTERCHANGE_FORMAT = 0x0201;
+
+    /**
+     * Bytes of JPEG data.
+     *
+     * Format: {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const JPEG_INTERCHANGE_FORMAT_LENGTH = 0x0202;
+
+    /**
+     * Color space transformation matrix coefficients.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 3.
+     */
+    const YCBCR_COEFFICIENTS = 0x0211;
+
+    /**
+     * Subsampling ratio of Y to C.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 2.
+     */
+    const YCBCR_SUB_SAMPLING = 0x0212;
+
+    /**
+     * Y and C positioning.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const YCBCR_POSITIONING = 0x0213;
+
+    /**
+     * Pair of black and white reference values.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 6.
+     */
+    const REFERENCE_BLACK_WHITE = 0x0214;
+
+    /**
+     * Related Image File Format
+     *
+     * Format: Unknown.
+     *
+     * Components: Unknown.
+     */
+    const RELATED_IMAGE_FILE_FORMAT = 0x1000;
+
+    /**
+     * Related Image Width
+     *
+     * Format: Unknown, probably {@link PelFormat::SHORT}?
+     *
+     * Components: Unknown, probably 1.
+     */
+    const RELATED_IMAGE_WIDTH = 0x1001;
+
+    /**
+     * Related Image Length
+     *
+     * Format: Unknown, probably {@link PelFormat::SHORT}?
+     *
+     * Components: Unknown, probably 1.
+     */
+    const RELATED_IMAGE_LENGTH = 0x1002;
+
+    /**
+     * Rating
+     *
+     * Format: {@link PelFormat::SHORT}
+     *
+     * Components: 1.
+    */
+    const RATING = 0x4746;
+
+    /**
+     * CFA Repeat Pattern Dim.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 2.
+     */
+    const CFA_REPEAT_PATTERN_DIM = 0x828D;
+
+    /**
+     * Battery level.
+     *
+     * Format: Unknown.
+     *
+     * Components: Unknown.
+     */
+    const BATTERY_LEVEL = 0x828F;
+
+    /**
+     * Copyright holder.
+     *
+     * Format: {@link PelFormat::ASCII}, modelled by the {@link
+     * PelEntryCopyright} class.
+     *
+     * Components: any number.
+     */
+    const COPYRIGHT = 0x8298;
+
+    /**
+     * Exposure Time
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const EXPOSURE_TIME = 0x829A;
+
+    /**
+     * FNumber
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const FNUMBER = 0x829D;
+
+    /**
+     * IPTC/NAA
+     *
+     * Format: {@link PelFormat::LONG}.
+     *
+     * Components: any number.
+     */
+    const IPTC_NAA = 0x83BB;
+
+    /**
+     * Exif IFD Pointer
+     *
+     * Format: {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const EXIF_IFD_POINTER = 0x8769;
+
+    /**
+     * Inter Color Profile
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: any number.
+     */
+    const INTER_COLOR_PROFILE = 0x8773;
+
+    /**
+     * Exposure Program
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const EXPOSURE_PROGRAM = 0x8822;
+
+    /**
+     * Spectral Sensitivity
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const SPECTRAL_SENSITIVITY = 0x8824;
+
+    /**
+     * GPS Info IFD Pointer
+     *
+     * Format: {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const GPS_INFO_IFD_POINTER = 0x8825;
+
+    /**
+     * ISO Speed Ratings
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 2.
+     */
+    const ISO_SPEED_RATINGS = 0x8827;
+
+    /**
+     * OECF
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: any number.
+     */
+    const OECF = 0x8828;
+
+    /**
+     * Exif version.
+     *
+     * Format: {@link PelFormat::UNDEFINED}, modelled by the {@link
+     * PelEntryVersion} class.
+     *
+     * Components: 4.
+     */
+    const EXIF_VERSION = 0x9000;
+
+    /**
+     * Date and time of original data generation.
+     *
+     * Format: {@link PelFormat::ASCII}, modelled by the {@link
+     * PelEntryTime} class.
+     *
+     * Components: 20.
+     */
+    const DATE_TIME_ORIGINAL = 0x9003;
+
+    /**
+     * Date and time of digital data generation.
+     *
+     * Format: {@link PelFormat::ASCII}, modelled by the {@link
+     * PelEntryTime} class.
+     *
+     * Components: 20.
+     */
+    const DATE_TIME_DIGITIZED = 0x9004;
+
+    /**
+     * Meaning of each component.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: 4.
+     */
+    const COMPONENTS_CONFIGURATION = 0x9101;
+
+    /**
+     * Image compression mode.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const COMPRESSED_BITS_PER_PIXEL = 0x9102;
+
+    /**
+     * Shutter speed
+     *
+     * Format: {@link PelFormat::SRATIONAL}.
+     *
+     * Components: 1.
+     */
+    const SHUTTER_SPEED_VALUE = 0x9201;
+
+    /**
+     * Aperture
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const APERTURE_VALUE = 0x9202;
+
+    /**
+     * Brightness
+     *
+     * Format: {@link PelFormat::SRATIONAL}.
+     *
+     * Components: 1.
+     */
+    const BRIGHTNESS_VALUE = 0x9203;
+
+    /**
+     * Exposure Bias
+     *
+     * Format: {@link PelFormat::SRATIONAL}.
+     *
+     * Components: 1.
+     */
+    const EXPOSURE_BIAS_VALUE = 0x9204;
+
+    /**
+     * Max Aperture Value
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const MAX_APERTURE_VALUE = 0x9205;
+
+    /**
+     * Subject Distance
+     *
+     * Format: {@link PelFormat::SRATIONAL}.
+     *
+     * Components: 1.
+     */
+    const SUBJECT_DISTANCE = 0x9206;
+
+    /**
+     * Metering Mode
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const METERING_MODE = 0x9207;
+
+    /**
+     * Light Source
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const LIGHT_SOURCE = 0x9208;
+
+    /**
+     * Flash
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const FLASH = 0x9209;
+
+    /**
+     * Focal Length
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const FOCAL_LENGTH = 0x920A;
+
+    /**
+     * Subject Area
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 4.
+     */
+    const SUBJECT_AREA = 0x9214;
+
+    /**
+     * Maker Note
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: any number.
+     */
+    const MAKER_NOTE = 0x927C;
+
+    /**
+     * User Comment
+     *
+     * Format: {@link PelFormat::UNDEFINED}, modelled by the {@link
+     * PelEntryUserComment} class.
+     *
+     * Components: any number.
+     */
+    const USER_COMMENT = 0x9286;
+
+    /**
+     * SubSec Time
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const SUB_SEC_TIME = 0x9290;
+
+    /**
+     * SubSec Time Original
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const SUB_SEC_TIME_ORIGINAL = 0x9291;
+
+    /**
+     * SubSec Time Digitized
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const SUB_SEC_TIME_DIGITIZED = 0x9292;
+
+    /**
+     * Windows XP Title
+     *
+     * Format: {@link PelFormat::BYTE}, modelled by the
+     * {@link PelEntryWindowsString} class.
+     *
+     * Components: any number.
+     */
+    const XP_TITLE = 0x9C9B;
+
+    /**
+     * Windows XP Comment
+     *
+     * Format: {@link PelFormat::BYTE}, modelled by the
+     * {@link PelEntryWindowsString} class.
+     *
+     * Components: any number.
+     */
+    const XP_COMMENT = 0x9C9C;
+
+    /**
+     * Windows XP Author
+     *
+     * Format: {@link PelFormat::BYTE}, modelled by the
+     * {@link PelEntryWindowsString} class.
+     *
+     * Components: any number.
+     */
+    const XP_AUTHOR = 0x9C9D;
+
+    /**
+     * Windows XP Keywords
+     *
+     * Format: {@link PelFormat::BYTE}, modelled by the
+     * {@link PelEntryWindowsString} class.
+     *
+     * Components: any number.
+     */
+    const XP_KEYWORDS = 0x9C9E;
+
+    /**
+     * Windows XP Subject
+     *
+     * Format: {@link PelFormat::BYTE}, modelled by the
+     * {@link PelEntryWindowsString} class.
+     *
+     * Components: any number.
+     */
+    const XP_SUBJECT = 0x9C9F;
+
+    /**
+     * Supported Flashpix version
+     *
+     * Format: {@link PelFormat::UNDEFINED}, modelled by the {@link
+     * PelEntryVersion} class.
+     *
+     * Components: 4.
+     */
+    const FLASH_PIX_VERSION = 0xA000;
+
+    /**
+     * Color space information.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const COLOR_SPACE = 0xA001;
+
+    /**
+     * Valid image width.
+     *
+     * Format: {@link PelFormat::SHORT} or {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const PIXEL_X_DIMENSION = 0xA002;
+
+    /**
+     * Valid image height.
+     *
+     * Format: {@link PelFormat::SHORT} or {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const PIXEL_Y_DIMENSION = 0xA003;
+
+    /**
+     * Related audio file.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: any number.
+     */
+    const RELATED_SOUND_FILE = 0xA004;
+
+    /**
+     * Interoperability IFD Pointer
+     *
+     * Format: {@link PelFormat::LONG}.
+     *
+     * Components: 1.
+     */
+    const INTEROPERABILITY_IFD_POINTER = 0xA005;
+
+    /**
+     * Flash energy.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const FLASH_ENERGY = 0xA20B;
+
+    /**
+     * Spatial frequency response.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: any number.
+     */
+    const SPATIAL_FREQUENCY_RESPONSE = 0xA20C;
+
+    /**
+     * Focal plane X resolution.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const FOCAL_PLANE_X_RESOLUTION = 0xA20E;
+
+    /**
+     * Focal plane Y resolution.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const FOCAL_PLANE_Y_RESOLUTION = 0xA20F;
+
+    /**
+     * Focal plane resolution unit.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const FOCAL_PLANE_RESOLUTION_UNIT = 0xA210;
+
+    /**
+     * Subject location.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const SUBJECT_LOCATION = 0xA214;
+
+    /**
+     * Exposure index.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const EXPOSURE_INDEX = 0xA215;
+
+    /**
+     * Sensing method.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const SENSING_METHOD = 0xA217;
+
+    /**
+     * File source.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: 1.
+     */
+    const FILE_SOURCE = 0xA300;
+
+    /**
+     * Scene type.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: 1.
+     */
+    const SCENE_TYPE = 0xA301;
+
+    /**
+     * CFA pattern.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: any number.
+     */
+    const CFA_PATTERN = 0xA302;
+
+    /**
+     * Custom image processing.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const CUSTOM_RENDERED = 0xA401;
+
+    /**
+     * Exposure mode.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const EXPOSURE_MODE = 0xA402;
+
+    /**
+     * White balance.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const WHITE_BALANCE = 0xA403;
+
+    /**
+     * Digital zoom ratio.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const DIGITAL_ZOOM_RATIO = 0xA404;
+
+    /**
+     * Focal length in 35mm film.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const FOCAL_LENGTH_IN_35MM_FILM = 0xA405;
+
+    /**
+     * Scene capture type.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const SCENE_CAPTURE_TYPE = 0xA406;
+
+    /**
+     * Gain control.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const GAIN_CONTROL = 0xA407;
+
+    /**
+     * Contrast.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const CONTRAST = 0xA408;
+
+    /**
+     * Saturation.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const SATURATION = 0xA409;
+
+    /**
+     * Sharpness.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const SHARPNESS = 0xA40A;
+
+    /**
+     * Device settings description.
+     *
+     * This tag indicates information on the picture-taking conditions
+     * of a particular camera model. The tag is used only to indicate
+     * the picture-taking conditions in the reader.
+     */
+    const DEVICE_SETTING_DESCRIPTION = 0xA40B;
+
+    /**
+     * Subject distance range.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const SUBJECT_DISTANCE_RANGE = 0xA40C;
+
+    /**
+     * Image unique ID.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 32.
+     */
+    const IMAGE_UNIQUE_ID = 0xA420;
+
+    /**
+     * Gamma.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GAMMA = 0xA500;
+
+    /**
+     * PrintIM
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: unknown.
+     */
+    const PRINT_IM = 0xC4A5;
+
+    /**
+     * GPS tag version.
+     *
+     * Format: {@link PelFormat::BYTE}.
+     *
+     * Components: 4.
+     */
+    const GPS_VERSION_ID = 0x0000;
+
+    /**
+     * North or South Latitude.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_LATITUDE_REF = 0x0001;
+
+    /**
+     * Latitude.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 3.
+     */
+    const GPS_LATITUDE = 0x0002;
+
+    /**
+     * East or West Longitude.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_LONGITUDE_REF = 0x0003;
+
+    /**
+     * Longitude.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 3.
+     */
+    const GPS_LONGITUDE = 0x0004;
+
+    /**
+     * Altitude reference.
+     *
+     * Format: {@link PelFormat::BYTE}.
+     *
+     * Components: 1.
+     */
+    const GPS_ALTITUDE_REF = 0x0005;
+
+    /**
+     * Altitude.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GPS_ALTITUDE = 0x0006;
+
+    /**
+     * GPS time (atomic clock).
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 3.
+     */
+    const GPS_TIME_STAMP = 0x0007;
+
+    /**
+     * GPS satellites used for measurement.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: Any.
+     */
+    const GPS_SATELLITES = 0x0008;
+
+    /**
+     * GPS receiver status.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_STATUS = 0x0009;
+
+    /**
+     * GPS measurement mode.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_MEASURE_MODE = 0x000A;
+
+    /**
+     * Measurement precision.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GPS_DOP = 0x000B;
+
+    /**
+     * Speed unit.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_SPEED_REF = 0x000C;
+
+    /**
+     * Speed of GPS receiver.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GPS_SPEED = 0x000D;
+
+    /**
+     * Reference for direction of movement.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_TRACK_REF = 0x000E;
+
+    /**
+     * Direction of movement.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GPS_TRACK = 0x000F;
+
+    /**
+     * Reference for direction of image.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_IMG_DIRECTION_REF = 0x0010;
+
+    /**
+     * Direction of image.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GPS_IMG_DIRECTION = 0x0011;
+
+    /**
+     * Geodetic survey data used.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: Any.
+     */
+    const GPS_MAP_DATUM = 0x0012;
+
+    /**
+     * Reference for latitude of destination.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_DEST_LATITUDE_REF = 0x0013;
+
+    /**
+     * Latitude of destination.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 3.
+     */
+    const GPS_DEST_LATITUDE = 0x0014;
+
+    /**
+     * Reference for longitude of destination.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_DEST_LONGITUDE_REF = 0x0015;
+
+    /**
+     * Longitude of destination.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 3.
+     */
+    const GPS_DEST_LONGITUDE = 0x0016;
+
+    /**
+     * Reference for bearing of destination.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_DEST_BEARING_REF = 0x0017;
+
+    /**
+     * Bearing of destination.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GPS_DEST_BEARING = 0x0018;
+
+    /**
+     * Reference for distance to destination.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 2.
+     */
+    const GPS_DEST_DISTANCE_REF = 0x0019;
+
+    /**
+     * Distance to destination.
+     *
+     * Format: {@link PelFormat::RATIONAL}.
+     *
+     * Components: 1.
+     */
+    const GPS_DEST_DISTANCE = 0x001A;
+
+    /**
+     * Name of GPS processing method.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: Any.
+     */
+    const GPS_PROCESSING_METHOD = 0x001B;
+
+    /**
+     * Name of GPS area.
+     *
+     * Format: {@link PelFormat::UNDEFINED}.
+     *
+     * Components: Any.
+     */
+    const GPS_AREA_INFORMATION = 0x001C;
+
+    /**
+     * GPS date.
+     *
+     * Format: {@link PelFormat::ASCII}.
+     *
+     * Components: 11.
+     */
+    const GPS_DATE_STAMP = 0x001D;
+
+    /**
+     * GPS differential correction.
+     *
+     * Format: {@link PelFormat::SHORT}.
+     *
+     * Components: 1.
+     */
+    const GPS_DIFFERENTIAL = 0x001E;
+
+    /**
+     * Values for tags short names.
+     */
+    protected static $exifTagsShort= array(
+        self::INTEROPERABILITY_INDEX         => 'InteroperabilityIndex',
+        self::INTEROPERABILITY_VERSION       => 'InteroperabilityVersion',
+        self::IMAGE_WIDTH                    => 'ImageWidth',
+        self::IMAGE_LENGTH                   => 'ImageLength',
+        self::BITS_PER_SAMPLE                => 'BitsPerSample',
+        self::COMPRESSION                    => 'Compression',
+        self::PHOTOMETRIC_INTERPRETATION     => 'PhotometricInterpretation',
+        self::FILL_ORDER                     => 'FillOrder',
+        self::DOCUMENT_NAME                  => 'DocumentName',
+        self::IMAGE_DESCRIPTION              => 'ImageDescription',
+        self::MAKE                           => 'Make',
+        self::MODEL                          => 'Model',
+        self::STRIP_OFFSETS                  => 'StripOffsets',
+        self::ORIENTATION                    => 'Orientation',
+        self::SAMPLES_PER_PIXEL              => 'SamplesPerPixel',
+        self::ROWS_PER_STRIP                 => 'RowsPerStrip',
+        self::STRIP_BYTE_COUNTS              => 'StripByteCounts',
+        self::X_RESOLUTION                   => 'XResolution',
+        self::Y_RESOLUTION                   => 'YResolution',
+        self::PLANAR_CONFIGURATION           => 'PlanarConfiguration',
+        self::RESOLUTION_UNIT                => 'ResolutionUnit',
+        self::TRANSFER_FUNCTION              => 'TransferFunction',
+        self::SOFTWARE                       => 'Software',
+        self::DATE_TIME                      => 'DateTime',
+        self::ARTIST                         => 'Artist',
+        self::WHITE_POINT                    => 'WhitePoint',
+        self::PRIMARY_CHROMATICITIES         => 'PrimaryChromaticities',
+        self::TRANSFER_RANGE                 => 'TransferRange',
+        self::JPEG_PROC                      => 'JPEGProc',
+        self::JPEG_INTERCHANGE_FORMAT        => 'JPEGInterchangeFormat',
+        self::JPEG_INTERCHANGE_FORMAT_LENGTH => 'JPEGInterchangeFormatLength',
+        self::YCBCR_COEFFICIENTS             => 'YCbCrCoefficients',
+        self::YCBCR_SUB_SAMPLING             => 'YCbCrSubSampling',
+        self::YCBCR_POSITIONING              => 'YCbCrPositioning',
+        self::REFERENCE_BLACK_WHITE          => 'ReferenceBlackWhite',
+        self::RELATED_IMAGE_FILE_FORMAT      => 'RelatedImageFileFormat',
+        self::RELATED_IMAGE_WIDTH            => 'RelatedImageWidth',
+        self::RELATED_IMAGE_LENGTH           => 'RelatedImageLength',
+        self::RATING                         => 'Rating',
+        self::CFA_REPEAT_PATTERN_DIM         => 'CFARepeatPatternDim',
+        self::CFA_PATTERN                    => 'CFAPattern',
+        self::BATTERY_LEVEL                  => 'BatteryLevel',
+        self::COPYRIGHT                      => 'Copyright',
+        self::EXPOSURE_TIME                  => 'ExposureTime',
+        self::FNUMBER                        => 'FNumber',
+        self::IPTC_NAA                       => 'IPTC/NAA',
+        self::EXIF_IFD_POINTER               => 'ExifIFDPointer',
+        self::INTER_COLOR_PROFILE            => 'InterColorProfile',
+        self::EXPOSURE_PROGRAM               => 'ExposureProgram',
+        self::SPECTRAL_SENSITIVITY           => 'SpectralSensitivity',
+        self::GPS_INFO_IFD_POINTER           => 'GPSInfoIFDPointer',
+        self::ISO_SPEED_RATINGS              => 'ISOSpeedRatings',
+        self::OECF                           => 'OECF',
+        self::EXIF_VERSION                   => 'ExifVersion',
+        self::DATE_TIME_ORIGINAL             => 'DateTimeOriginal',
+        self::DATE_TIME_DIGITIZED            => 'DateTimeDigitized',
+        self::COMPONENTS_CONFIGURATION       => 'ComponentsConfiguration',
+        self::COMPRESSED_BITS_PER_PIXEL      => 'CompressedBitsPerPixel',
+        self::SHUTTER_SPEED_VALUE            => 'ShutterSpeedValue',
+        self::APERTURE_VALUE                 => 'ApertureValue',
+        self::BRIGHTNESS_VALUE               => 'BrightnessValue',
+        self::EXPOSURE_BIAS_VALUE            => 'ExposureBiasValue',
+        self::MAX_APERTURE_VALUE             => 'MaxApertureValue',
+        self::SUBJECT_DISTANCE               => 'SubjectDistance',
+        self::METERING_MODE                  => 'MeteringMode',
+        self::LIGHT_SOURCE                   => 'LightSource',
+        self::FLASH                          => 'Flash',
+        self::FOCAL_LENGTH                   => 'FocalLength',
+        self::MAKER_NOTE                     => 'MakerNote',
+        self::USER_COMMENT                   => 'UserComment',
+        self::SUB_SEC_TIME                   => 'SubSecTime',
+        self::SUB_SEC_TIME_ORIGINAL          => 'SubSecTimeOriginal',
+        self::SUB_SEC_TIME_DIGITIZED         => 'SubSecTimeDigitized',
+        self::XP_TITLE                       => 'WindowsXPTitle',
+        self::XP_COMMENT                     => 'WindowsXPComment',
+        self::XP_AUTHOR                      => 'WindowsXPAuthor',
+        self::XP_KEYWORDS                    => 'WindowsXPKeywords',
+        self::XP_SUBJECT                     => 'WindowsXPSubject',
+        self::FLASH_PIX_VERSION              => 'FlashPixVersion',
+        self::COLOR_SPACE                    => 'ColorSpace',
+        self::PIXEL_X_DIMENSION              => 'PixelXDimension',
+        self::PIXEL_Y_DIMENSION              => 'PixelYDimension',
+        self::RELATED_SOUND_FILE             => 'RelatedSoundFile',
+        self::INTEROPERABILITY_IFD_POINTER   => 'InteroperabilityIFDPointer',
+        self::FLASH_ENERGY                   => 'FlashEnergy',
+        self::SPATIAL_FREQUENCY_RESPONSE     => 'SpatialFrequencyResponse',
+        self::FOCAL_PLANE_X_RESOLUTION       => 'FocalPlaneXResolution',
+        self::FOCAL_PLANE_Y_RESOLUTION       => 'FocalPlaneYResolution',
+        self::FOCAL_PLANE_RESOLUTION_UNIT    => 'FocalPlaneResolutionUnit',
+        self::SUBJECT_LOCATION               => 'SubjectLocation',
+        self::EXPOSURE_INDEX                 => 'ExposureIndex',
+        self::SENSING_METHOD                 => 'SensingMethod',
+        self::FILE_SOURCE                    => 'FileSource',
+        self::SCENE_TYPE                     => 'SceneType',
+        self::SUBJECT_AREA                   => 'SubjectArea',
+        self::CUSTOM_RENDERED                => 'CustomRendered',
+        self::EXPOSURE_MODE                  => 'ExposureMode',
+        self::WHITE_BALANCE                  => 'WhiteBalance',
+        self::DIGITAL_ZOOM_RATIO             => 'DigitalZoomRatio',
+        self::FOCAL_LENGTH_IN_35MM_FILM      => 'FocalLengthIn35mmFilm',
+        self::SCENE_CAPTURE_TYPE             => 'SceneCaptureType',
+        self::GAIN_CONTROL                   => 'GainControl',
+        self::CONTRAST                       => 'Contrast',
+        self::SATURATION                     => 'Saturation',
+        self::SHARPNESS                      => 'Sharpness',
+        self::DEVICE_SETTING_DESCRIPTION     => 'DeviceSettingDescription',
+        self::SUBJECT_DISTANCE_RANGE         => 'SubjectDistanceRange',
+        self::IMAGE_UNIQUE_ID                => 'ImageUniqueID',
+        self::GAMMA                          => 'Gamma',
+        self::PRINT_IM                       => 'PrintIM',
+    );
+
+    /**
+     * Values for tags titles.
+     */
+    protected static $exifTagsTitle = array(
+        self::INTEROPERABILITY_INDEX         => 'Interoperability Index',
+        self::INTEROPERABILITY_VERSION       => 'Interoperability Version',
+        self::IMAGE_WIDTH                    => 'Image Width',
+        self::IMAGE_LENGTH                   => 'Image Length',
+        self::BITS_PER_SAMPLE                => 'Bits per Sample',
+        self::COMPRESSION                    => 'Compression',
+        self::PHOTOMETRIC_INTERPRETATION     => 'Photometric Interpretation',
+        self::FILL_ORDER                     => 'Fill Order',
+        self::DOCUMENT_NAME                  => 'Document Name',
+        self::IMAGE_DESCRIPTION              => 'Image Description',
+        self::MAKE                           => 'Manufacturer',
+        self::MODEL                          => 'Model',
+        self::STRIP_OFFSETS                  => 'Strip Offsets',
+        self::ORIENTATION                    => 'Orientation',
+        self::SAMPLES_PER_PIXEL              => 'Samples per Pixel',
+        self::ROWS_PER_STRIP                 => 'Rows per Strip',
+        self::STRIP_BYTE_COUNTS              => 'Strip Byte Count',
+        self::X_RESOLUTION                   => 'x-Resolution',
+        self::Y_RESOLUTION                   => 'y-Resolution',
+        self::PLANAR_CONFIGURATION           => 'Planar Configuration',
+        self::RESOLUTION_UNIT                => 'Resolution Unit',
+        self::TRANSFER_FUNCTION              => 'Transfer Function',
+        self::SOFTWARE                       => 'Software',
+        self::DATE_TIME                      => 'Date and Time',
+        self::ARTIST                         => 'Artist',
+        self::WHITE_POINT                    => 'White Point',
+        self::PRIMARY_CHROMATICITIES         => 'Primary Chromaticities',
+        self::TRANSFER_RANGE                 => 'Transfer Range',
+        self::JPEG_PROC                      => 'JPEG Process',
+        self::JPEG_INTERCHANGE_FORMAT        => 'JPEG Interchange Format',
+        self::JPEG_INTERCHANGE_FORMAT_LENGTH => 'JPEG Interchange Format Length',
+        self::YCBCR_COEFFICIENTS             => 'YCbCr Coefficients',
+        self::YCBCR_SUB_SAMPLING             => 'YCbCr Sub-Sampling',
+        self::YCBCR_POSITIONING              => 'YCbCr Positioning',
+        self::REFERENCE_BLACK_WHITE          => 'Reference Black/White',
+        self::RELATED_IMAGE_FILE_FORMAT      => 'Related Image File Format',
+        self::RELATED_IMAGE_WIDTH            => 'Related Image Width',
+        self::RELATED_IMAGE_LENGTH           => 'Related Image Length',
+        self::CFA_REPEAT_PATTERN_DIM         => 'CFA Repeat Pattern Dim',
+        self::CFA_PATTERN                    => 'CFA Pattern',
+        self::BATTERY_LEVEL                  => 'Battery Level',
+        self::COPYRIGHT                      => 'Copyright',
+        self::EXPOSURE_TIME                  => 'Exposure Time',
+        self::FNUMBER                        => 'FNumber',
+        self::IPTC_NAA                       => 'IPTC/NAA',
+        self::EXIF_IFD_POINTER               => 'Exif IFD Pointer',
+        self::INTER_COLOR_PROFILE            => 'Inter Color Profile',
+        self::EXPOSURE_PROGRAM               => 'Exposure Program',
+        self::SPECTRAL_SENSITIVITY           => 'Spectral Sensitivity',
+        self::GPS_INFO_IFD_POINTER           => 'GPS Info IFD Pointer',
+        self::ISO_SPEED_RATINGS              => 'ISO Speed Ratings',
+        self::OECF                           => 'OECF',
+        self::EXIF_VERSION                   => 'Exif Version',
+        self::DATE_TIME_ORIGINAL             => 'Date and Time (original)',
+        self::DATE_TIME_DIGITIZED            => 'Date and Time (digitized)',
+        self::COMPONENTS_CONFIGURATION       => 'Components Configuration',
+        self::COMPRESSED_BITS_PER_PIXEL      => 'Compressed Bits per Pixel',
+        self::SHUTTER_SPEED_VALUE            => 'Shutter speed',
+        self::APERTURE_VALUE                 => 'Aperture',
+        self::BRIGHTNESS_VALUE               => 'Brightness',
+        self::EXPOSURE_BIAS_VALUE            => 'Exposure Bias',
+        self::MAX_APERTURE_VALUE             => 'Max Aperture Value',
+        self::SUBJECT_DISTANCE               => 'Subject Distance',
+        self::METERING_MODE                  => 'Metering Mode',
+        self::LIGHT_SOURCE                   => 'Light Source',
+        self::FLASH                          => 'Flash',
+        self::FOCAL_LENGTH                   => 'Focal Length',
+        self::MAKER_NOTE                     => 'Maker Note',
+        self::USER_COMMENT                   => 'User Comment',
+        self::SUB_SEC_TIME                   => 'SubSec Time',
+        self::SUB_SEC_TIME_ORIGINAL          => 'SubSec Time Original',
+        self::SUB_SEC_TIME_DIGITIZED         => 'SubSec Time Digitized',
+        self::XP_TITLE                       => 'Windows XP Title',
+        self::XP_COMMENT                     => 'Windows XP Comment',
+        self::XP_AUTHOR                      => 'Windows XP Author',
+        self::XP_KEYWORDS                    => 'Windows XP Keywords',
+        self::XP_SUBJECT                     => 'Windows XP Subject',
+        self::FLASH_PIX_VERSION              => 'FlashPix Version',
+        self::COLOR_SPACE                    => 'Color Space',
+        self::PIXEL_X_DIMENSION              => 'Pixel x-Dimension',
+        self::PIXEL_Y_DIMENSION              => 'Pixel y-Dimension',
+        self::RELATED_SOUND_FILE             => 'Related Sound File',
+        self::INTEROPERABILITY_IFD_POINTER   => 'Interoperability IFD Pointer',
+        self::FLASH_ENERGY                   => 'Flash Energy',
+        self::SPATIAL_FREQUENCY_RESPONSE     => 'Spatial Frequency Response',
+        self::FOCAL_PLANE_X_RESOLUTION       => 'Focal Plane x-Resolution',
+        self::FOCAL_PLANE_Y_RESOLUTION       => 'Focal Plane y-Resolution',
+        self::FOCAL_PLANE_RESOLUTION_UNIT    => 'Focal Plane Resolution Unit',
+        self::SUBJECT_LOCATION               => 'Subject Location',
+        self::EXPOSURE_INDEX                 => 'Exposure index',
+        self::SENSING_METHOD                 => 'Sensing Method',
+        self::FILE_SOURCE                    => 'File Source',
+        self::SCENE_TYPE                     => 'Scene Type',
+        self::SUBJECT_AREA                   => 'Subject Area',
+        self::CUSTOM_RENDERED                => 'Custom Rendered',
+        self::EXPOSURE_MODE                  => 'Exposure Mode',
+        self::WHITE_BALANCE                  => 'White Balance',
+        self::DIGITAL_ZOOM_RATIO             => 'Digital Zoom Ratio',
+        self::FOCAL_LENGTH_IN_35MM_FILM      => 'Focal Length In 35mm Film',
+        self::SCENE_CAPTURE_TYPE             => 'Scene Capture Type',
+        self::GAIN_CONTROL                   => 'Gain Control',
+        self::CONTRAST                       => 'Contrast',
+        self::SATURATION                     => 'Saturation',
+        self::SHARPNESS                      => 'Sharpness',
+        self::DEVICE_SETTING_DESCRIPTION     => 'Device Setting Description',
+        self::SUBJECT_DISTANCE_RANGE         => 'Subject Distance Range',
+        self::IMAGE_UNIQUE_ID                => 'Image Unique ID',
+        self::GAMMA                          => 'Gamma',
+        self::PRINT_IM                       => 'Print IM',
+    );
+
+    /**
+     * Values for gps tags short names.
+     */
+    protected static $gpsTagsShort = array(
+        self::GPS_VERSION_ID         => 'GPSVersionID',
+        self::GPS_LATITUDE_REF       => 'GPSLatitudeRef',
+        self::GPS_LATITUDE           => 'GPSLatitude',
+        self::GPS_LONGITUDE_REF      => 'GPSLongitudeRef',
+        self::GPS_LONGITUDE          => 'GPSLongitude',
+        self::GPS_ALTITUDE_REF       => 'GPSAltitudeRef',
+        self::GPS_ALTITUDE           => 'GPSAltitude',
+        self::GPS_TIME_STAMP         => 'GPSTimeStamp',
+        self::GPS_SATELLITES         => 'GPSSatellites',
+        self::GPS_STATUS             => 'GPSStatus',
+        self::GPS_MEASURE_MODE       => 'GPSMeasureMode',
+        self::GPS_DOP                => 'GPSDOP',
+        self::GPS_SPEED_REF          => 'GPSSpeedRef',
+        self::GPS_SPEED              => 'GPSSpeed',
+        self::GPS_TRACK_REF          => 'GPSTrackRef',
+        self::GPS_TRACK              => 'GPSTrack',
+        self::GPS_IMG_DIRECTION_REF  => 'GPSImgDirectionRef',
+        self::GPS_IMG_DIRECTION      => 'GPSImgDirection',
+        self::GPS_MAP_DATUM          => 'GPSMapDatum',
+        self::GPS_DEST_LATITUDE_REF  => 'GPSDestLatitudeRef',
+        self::GPS_DEST_LATITUDE      => 'GPSDestLatitude',
+        self::GPS_DEST_LONGITUDE_REF => 'GPSDestLongitudeRef',
+        self::GPS_DEST_LONGITUDE     => 'GPSDestLongitude',
+        self::GPS_DEST_BEARING_REF   => 'GPSDestBearingRef',
+        self::GPS_DEST_BEARING       => 'GPSDestBearing',
+        self::GPS_DEST_DISTANCE_REF  => 'GPSDestDistanceRef',
+        self::GPS_DEST_DISTANCE      => 'GPSDestDistance',
+        self::GPS_PROCESSING_METHOD  => 'GPSProcessingMethod',
+        self::GPS_AREA_INFORMATION   => 'GPSAreaInformation',
+        self::GPS_DATE_STAMP         => 'GPSDateStamp',
+        self::GPS_DIFFERENTIAL       => 'GPSDifferential',
+    );
+
+    /**
+     * Returns a string from container with key $tag and subcontainer index of $idx
+     *
+     * @param array $container
+     *            {@link PelTag::EXIF_TAGS_SHORT}, {@link PelTag::EXIF_TAGS_TITLE},
+     *            {@link PelTag::GPS_TAGS_SHORT} or {@link PelTag::GPS_TAGS_TITLE} container.
+     * @param PelTag $tag
+     *            the tag.
+     *
+     * @return string short name or long name of the tag.
+     */
+    public static function getValue($container, $tag)
+    {
+        if (isset($container[ $tag ])) {
+            return $container[ $tag ];
+        }
+
+        return self::unknownTag($tag);
+    }
+
+    /**
+     * Reverse lookup of a tag id by its short name. Return false for the unknown tag name.
+     *
+     * @param string $name
+     *            tag short name.
+     *
+     * @return mixed (bool|int)
+     *            the tag.
+     */
+    public static function getTagByName($name)
+    {
+        $k = array_search($name, self::$exifTagsShort);
+        if ($k !== false) {
+            return $k;
+        }
+
+        return array_search($name, static::$gpsTagsShort);
+    }
+
+    /**
+     * Returns string defining unknown tag.
+     *
+     * @param int $tag
+     *            the tag.
+     *
+     * @return string
+     *            description string.
+     */
+    protected static function unknownTag($tag)
+    {
+        return Pel::fmt('Unknown: 0x%04X', $tag);
+    }
+
+    /**
+     * Returns a short name for an Exif tag.
+     *
+     * @param int $type
+     *            the IFD type of the tag, one of {@link PelIfd::IFD0},
+     *            {@link PelIfd::IFD1}, {@link PelIfd::EXIF}, {@link PelIfd::GPS},
+     *            or {@link PelIfd::INTEROPERABILITY}.
+     *
+     * @param PelTag $tag
+     *            the tag.
+     *
+     * @return string the short name of the tag, e.g., 'ImageWidth' for
+     *         the {@link IMAGE_WIDTH} tag. If the tag is not known, the string
+     *         'Unknown:0xTTTT' will be returned where 'TTTT' is the hexadecimal
+     *         representation of the tag.
+     */
+    public static function getName($type, $tag)
+    {
+        switch ($type) {
+            case PelIfd::IFD0:
+            case PelIfd::IFD1:
+            case PelIfd::EXIF:
+            case PelIfd::INTEROPERABILITY:
+                return self::getValue(self::$exifTagsShort, $tag);
+            case PelIfd::GPS:
+                return self::getValue(self::$gpsTagsShort, $tag);
+        }
+
+        return self::unknownTag($tag);
+    }
+
+    /**
+     * Returns a title for an Exif tag.
+     *
+     * @param int $type
+     *            the IFD type of the tag, one of {@link PelIfd::IFD0},
+     *            {@link PelIfd::IFD1}, {@link PelIfd::EXIF}, {@link PelIfd::GPS},
+     *            or {@link PelIfd::INTEROPERABILITY}.
+     *
+     * @param PelTag $tag
+     *            the tag.
+     *
+     * @return string the title of the tag, e.g., 'Image Width' for the
+     *         {@link IMAGE_WIDTH} tag. If the tag isn't known, the string
+     *         'Unknown Tag: 0xTT' will be returned where 'TT' is the
+     *         hexadecimal representation of the tag.
+     */
+    public function getTitle($type, $tag)
+    {
+        switch ($type) {
+            case PelIfd::IFD0:
+            case PelIfd::IFD1:
+            case PelIfd::EXIF:
+            case PelIfd::INTEROPERABILITY:
+                return Pel::tra(self::getValue(self::$exifTagsTitle, $tag));
+            case PelIfd::GPS:
+                return Pel::tra(self::getValue(self::$gpsTagsShort, $tag));
+        }
+
+        return self::unknownTag($tag);
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelTiff.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelTiff.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd0602350ff18d4677993afcc0a3cffd2cbc3bd7
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelTiff.php
@@ -0,0 +1,314 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with TIFF data.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Class for handling TIFF data.
+ *
+ * Exif data is actually an extension of the TIFF file format. TIFF
+ * images consist of a number of {@link PelIfd Image File Directories}
+ * (IFDs), each containing a number of {@link PelEntry entries}. The
+ * IFDs are linked to each other --- one can get hold of the first one
+ * with the {@link getIfd()} method.
+ *
+ * To parse a TIFF image for Exif data one would do:
+ *
+ * <code>
+ * $tiff = new PelTiff($data);
+ * $ifd0 = $tiff->getIfd();
+ * $exif = $ifd0->getSubIfd(PelIfd::EXIF);
+ * $ifd1 = $ifd0->getNextIfd();
+ * </code>
+ *
+ * Should one have some image data of an unknown type, then the {@link
+ * PelTiff::isValid()} function is handy: it will quickly test if the
+ * data could be valid TIFF data. The {@link PelJpeg::isValid()}
+ * function does the same for JPEG images.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ */
+class PelTiff
+{
+
+    /**
+     * TIFF header.
+     *
+     * This must follow after the two bytes indicating the byte order.
+     */
+    const TIFF_HEADER = 0x002A;
+
+    /**
+     * The first Image File Directory, if any.
+     *
+     * If set, then the type of the IFD must be {@link PelIfd::IFD0}.
+     *
+     * @var PelIfd
+     */
+    private $ifd = null;
+
+    /**
+     * Construct a new object for holding TIFF data.
+     *
+     * The new object will be empty (with no {@link PelIfd}) unless an
+     * argument is given from which it can initialize itself. This can
+     * either be the filename of a TIFF image or a {@link PelDataWindow}
+     * object.
+     *
+     * Use {@link setIfd()} to explicitly set the IFD.
+     *
+     * @param boolean|string|PelDataWindow $data;
+     */
+    public function __construct($data = false)
+    {
+        if ($data === false) {
+            return;
+        }
+        if (is_string($data)) {
+            Pel::debug('Initializing PelTiff object from %s', $data);
+            $this->loadFile($data);
+        } elseif ($data instanceof PelDataWindow) {
+            Pel::debug('Initializing PelTiff object from PelDataWindow.');
+            $this->load($data);
+        } else {
+            throw new PelInvalidArgumentException('Bad type for $data: %s', gettype($data));
+        }
+    }
+
+    /**
+     * Load TIFF data.
+     *
+     * The data given will be parsed and an internal tree representation
+     * will be built. If the data cannot be parsed correctly, a {@link
+     * PelInvalidDataException} is thrown, explaining the problem.
+     *
+     * @param
+     *            d
+     *            PelDataWindow the data from which the object will be
+     *            constructed. This should be valid TIFF data, coming either
+     *            directly from a TIFF image or from the Exif data in a JPEG image.
+     */
+    public function load(PelDataWindow $d)
+    {
+        Pel::debug('Parsing %d bytes of TIFF data...', $d->getSize());
+
+        /*
+         * There must be at least 8 bytes available: 2 bytes for the byte
+         * order, 2 bytes for the TIFF header, and 4 bytes for the offset
+         * to the first IFD.
+         */
+        if ($d->getSize() < 8) {
+            throw new PelInvalidDataException('Expected at least 8 bytes of TIFF ' . 'data, found just %d bytes.', $d->getSize());
+        }
+        /* Byte order */
+        if ($d->strcmp(0, 'II')) {
+            Pel::debug('Found Intel byte order');
+            $d->setByteOrder(PelConvert::LITTLE_ENDIAN);
+        } elseif ($d->strcmp(0, 'MM')) {
+            Pel::debug('Found Motorola byte order');
+            $d->setByteOrder(PelConvert::BIG_ENDIAN);
+        } else {
+            throw new PelInvalidDataException('Unknown byte order found in TIFF ' . 'data: 0x%2X%2X', $d->getByte(0), $d->getByte(1));
+        }
+
+        /* Verify the TIFF header */
+        if ($d->getShort(2) != self::TIFF_HEADER) {
+            throw new PelInvalidDataException('Missing TIFF magic value.');
+        }
+        /* IFD 0 offset */
+        $offset = $d->getLong(4);
+        Pel::debug('First IFD at offset %d.', $offset);
+
+        if ($offset > 0) {
+            /*
+             * Parse the first IFD, this will automatically parse the
+             * following IFDs and any sub IFDs.
+             */
+            $this->ifd = new PelIfd(PelIfd::IFD0);
+            $this->ifd->load($d, $offset);
+        }
+    }
+
+    /**
+     * Load data from a file into a TIFF object.
+     *
+     * @param string $filename
+     *            the filename. This must be a readable file.
+     */
+    public function loadFile($filename)
+    {
+        $this->load(new PelDataWindow(file_get_contents($filename)));
+    }
+
+    /**
+     * Set the first IFD.
+     *
+     * @param PelIfd $ifd
+     *            the new first IFD, which must be of type {@link
+     *            PelIfd::IFD0}.
+     */
+    public function setIfd(PelIfd $ifd)
+    {
+        if ($ifd->getType() != PelIfd::IFD0) {
+            throw new PelInvalidDataException('Invalid type of IFD: %d, expected %d.', $ifd->getType(), PelIfd::IFD0);
+        }
+        $this->ifd = $ifd;
+    }
+
+    /**
+     * Return the first IFD.
+     *
+     * @return PelIfd the first IFD contained in the TIFF data, if any.
+     *         If there is no IFD null will be returned.
+     */
+    public function getIfd()
+    {
+        return $this->ifd;
+    }
+
+    /**
+     * Turn this object into bytes.
+     *
+     * TIFF images can have {@link PelConvert::LITTLE_ENDIAN
+     * little-endian} or {@link PelConvert::BIG_ENDIAN big-endian} byte
+     * order, and so this method takes an argument specifying that.
+     *
+     * @param PelByteOrder $order
+     *            the desired byte order of the TIFF data.
+     *            This should be one of {@link PelConvert::LITTLE_ENDIAN} or {@link
+     *            PelConvert::BIG_ENDIAN}.
+     *
+     * @return string the bytes representing this object.
+     */
+    public function getBytes($order = PelConvert::LITTLE_ENDIAN)
+    {
+        if ($order == PelConvert::LITTLE_ENDIAN) {
+            $bytes = 'II';
+        } else {
+            $bytes = 'MM';
+        }
+
+        /* TIFF magic number --- fixed value. */
+        $bytes .= PelConvert::shortToBytes(self::TIFF_HEADER, $order);
+
+        if ($this->ifd !== null) {
+            /*
+             * IFD 0 offset. We will always start IDF 0 at an offset of 8
+             * bytes (2 bytes for byte order, another 2 bytes for the TIFF
+             * header, and 4 bytes for the IFD 0 offset make 8 bytes
+             * together).
+             */
+            $bytes .= PelConvert::longToBytes(8, $order);
+
+            /*
+             * The argument specifies the offset of this IFD. The IFD will
+             * use this to calculate offsets from the entries to their data,
+             * all those offsets are absolute offsets counted from the
+             * beginning of the data.
+             */
+            $bytes .= $this->ifd->getBytes(8, $order);
+        } else {
+            $bytes .= PelConvert::longToBytes(0, $order);
+        }
+
+        return $bytes;
+    }
+
+    /**
+     * Save the TIFF object as a TIFF image in a file.
+     *
+     * @param
+     *            string the filename to save in. An existing file with the
+     *            same name will be overwritten!
+     *
+     * @return integer|FALSE The number of bytes that were written to the
+     *         file, or FALSE on failure.
+     */
+    public function saveFile($filename)
+    {
+        return file_put_contents($filename, $this->getBytes());
+    }
+
+    /**
+     * Return a string representation of this object.
+     *
+     * @return string a string describing this object. This is mostly useful
+     *         for debugging.
+     */
+    public function __toString()
+    {
+        $str = Pel::fmt("Dumping TIFF data...\n");
+        if ($this->ifd !== null) {
+            $str .= $this->ifd->__toString();
+        }
+
+        return $str;
+    }
+
+    /**
+     * Check if data is valid TIFF data.
+     *
+     * This will read just enough data from the data window to determine
+     * if the data could be a valid TIFF data. This means that the
+     * check is more like a heuristic than a rigorous check.
+     *
+     * @param PelDataWindow $d
+     *            the bytes that will be examined.
+     *
+     * @return boolean true if the data looks like valid TIFF data,
+     *         false otherwise.
+     *
+     * @see PelJpeg::isValid()
+     */
+    public static function isValid(PelDataWindow $d)
+    {
+        /* First check that we have enough data. */
+        if ($d->getSize() < 8) {
+            return false;
+        }
+
+        /* Byte order */
+        if ($d->strcmp(0, 'II')) {
+            $d->setByteOrder(PelConvert::LITTLE_ENDIAN);
+        } elseif ($d->strcmp(0, 'MM')) {
+            Pel::debug('Found Motorola byte order');
+            $d->setByteOrder(PelConvert::BIG_ENDIAN);
+        } else {
+            return false;
+        }
+
+        /* Verify the TIFF header */
+        return $d->getShort(2) == self::TIFF_HEADER;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelUnexpectedFormatException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelUnexpectedFormatException.php
new file mode 100644
index 0000000000000000000000000000000000000000..cfbadaa57d1895cc0b925916c0235a47135801dd
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelUnexpectedFormatException.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif entries.
+ *
+ * This file defines two exception classes and the abstract class
+ * {@link PelEntry} which provides the basic methods that all Exif
+ * entries will have. All Exif entries will be represented by
+ * descendants of the {@link PelEntry} class --- the class itself is
+ * abstract and so it cannot be instantiated.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+
+/**
+ * Exception indicating that an unexpected format was found.
+ *
+ * The documentation for each tag in {@link PelTag} will detail any
+ * constrains.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelUnexpectedFormatException extends PelEntryException
+{
+
+    /**
+     * Construct a new exception indicating an invalid format.
+     *
+     * @param int $type
+     *            the type of IFD.
+     *
+     * @param int $tag
+     *            the tag for which the violation was found as defined in {@link PelTag}
+     *
+     * @param int $found
+     *            the format found as defined in {@link PelFormat}
+     *
+     * @param int $expected
+     *            the expected as defined in {@link PelFormat}
+     */
+    public function __construct($type, $tag, $found, $expected)
+    {
+        parent::__construct(
+            'Unexpected format found for %s tag: PelFormat::%s. Expected PelFormat::%s instead.',
+            PelTag::getName($type, $tag),
+            strtoupper(PelFormat::getName($found)),
+            strtoupper(PelFormat::getName($expected)));
+        $this->tag = $tag;
+        $this->type = $type;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelWrongComponentCountException.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelWrongComponentCountException.php
new file mode 100644
index 0000000000000000000000000000000000000000..5dd3509b11ef2040d98fc4ebef4cb2a6b42eacb5
--- /dev/null
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_data/pel-0.9.6/src/PelWrongComponentCountException.php
@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * PEL: PHP Exif Library.
+ * A library with support for reading and
+ * writing all Exif headers in JPEG and TIFF images using PHP.
+ *
+ * Copyright (C) 2004, 2005, 2006 Martin Geisler.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in the file COPYING; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+namespace lsolesen\pel;
+
+/**
+ * Classes for dealing with Exif entries.
+ *
+ * This file defines two exception classes and the abstract class
+ * {@link PelEntry} which provides the basic methods that all Exif
+ * entries will have. All Exif entries will be represented by
+ * descendants of the {@link PelEntry} class --- the class itself is
+ * abstract and so it cannot be instantiated.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
+ *          License (GPL)
+ * @package PEL
+ */
+use lsolesen\pel\PelTag;
+
+/**
+ * Exception indicating that an unexpected number of components was
+ * found.
+ *
+ * Some tags have strict limits as to the allowed number of
+ * components, and this exception is thrown if the data violates such
+ * a constraint. The documentation for each tag in {@link PelTag}
+ * explains the expected number of components.
+ *
+ * @author Martin Geisler <mgeisler@users.sourceforge.net>
+ * @package PEL
+ * @subpackage Exception
+ */
+class PelWrongComponentCountException extends \lsolesen\pel\PelEntryException
+{
+
+    /**
+     * Construct a new exception indicating a wrong number of
+     * components.
+     *
+     * @param int $type
+     *            the type of IFD.
+     *
+     * @param PelTag $tag
+     *            the tag for which the violation was found.
+     *
+     * @param int $found
+     *            the number of components found.
+     *
+     * @param int $expected
+     *            the expected number of components.
+     */
+    public function __construct($type, $tag, $found, $expected)
+    {
+        parent::__construct('Wrong number of components found for %s tag: %d. ' . 'Expected %d.', PelTag::getName($type, $tag), $found, $expected);
+        $this->tag = $tag;
+        $this->type = $type;
+    }
+}
diff --git a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_gallery_display/package.module.nextgen_gallery_display.php b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_gallery_display/package.module.nextgen_gallery_display.php
index 9a73a92caaf617b29717cc5380fa0129dcf5da7c..2af60416c4b720a41894eaed8cac25201daea2fc 100644
--- a/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_gallery_display/package.module.nextgen_gallery_display.php
+++ b/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_gallery_display/package.module.nextgen_gallery_display.php
@@ -2291,6 +2291,38 @@ class Mixin_Display_Type_Form extends Mixin
     {
         $this->object->implement('I_Display_Type_Form');
     }
+    /**
+     * A wrapper to wp_enqueue_script() and ATP's mark_script()
+     *
+     * Unlike wp_enqueue_script() the version parameter is last as NGG should always use NGG_SCRIPT_VERSION
+     * @param string $handle
+     * @param string $source
+     * @param array $dependencies
+     * @param bool $in_footer
+     * @param string $version
+     */
+    public function enqueue_script($handle, $source = '', $dependencies = array(), $in_footer = FALSE, $version = NGG_SCRIPT_VERSION)
+    {
+        wp_enqueue_script($handle, $source, $dependencies, $version, $in_footer);
+        $atp = C_Attach_Controller::get_instance();
+        if ($atp !== NULL) {
+            $atp->mark_script($handle);
+        }
+    }
+    /**
+     * A wrapper to wp_enqueue_style()
+     *
+     * Unlike wp_enqueue_style() the version parameter is last as NGG should always use NGG_SCRIPT_VERSION
+     * @param string $handle
+     * @param string $source
+     * @param array $dependencies
+     * @param string $media
+     * @param string $version
+     */
+    public function enqueue_style($handle, $source = '', $dependencies = array(), $media = 'all', $version = NGG_SCRIPT_VERSION)
+    {
+        wp_enqueue_style($handle, $source, $dependencies, $version, $media);
+    }
     /**
      * Returns the name of the display type. Sub-class should override
      * @throws Exception
diff --git a/wp-content/plugins/nextgen-gallery/readme.txt b/wp-content/plugins/nextgen-gallery/readme.txt
index d0ece7b53c4fa6634d6f1957ba01ad51ed3695f5..6c72e52169cee7717364a19af9fbd5e060b6da93 100644
--- a/wp-content/plugins/nextgen-gallery/readme.txt
+++ b/wp-content/plugins/nextgen-gallery/readme.txt
@@ -2,8 +2,8 @@
 Contributors: photocrati, imagely
 Tags: wordpress gallery plugin, gallery, nextgen, nextgen gallery, photo gallery, image gallery, photography, slideshow, images, photo, photo album, watermark
 Requires at least: 4.0.0
-Stable tag: 2.2.12
-Tested up to: 4.8.0
+Stable tag: 2.3.0
+Tested up to: 4.8.1
 License: GPLv2
 
 The most popular WordPress gallery plugin and one of the most popular plugins of all time with over 18 million downloads.
@@ -187,6 +187,10 @@ For more information, feel free to visit the official website for the NextGEN Ga
 
 == Changelog ==
 
+= V2.2.14 - 09.18.2017 =
+* NEW:   EXIF and IPTC metadata are copied to new images when generating thumbnails, watermarks, or new sizes
+* Fixed: Metadata is read and preserved when "Resized images after upload" feature is enabled
+
 = V2.2.12 - 08.01.2017 =
 * Secured: Disabled Flash backend in plupload
 * Changed: Upgraded PHP-Parser version used when building plugin zips