diff --git a/3.0/modules/picasa_faces/helpers/picasa_faces_event.php b/3.0/modules/picasa_faces/helpers/picasa_faces_event.php
index 29886370..605e286b 100644
--- a/3.0/modules/picasa_faces/helpers/picasa_faces_event.php
+++ b/3.0/modules/picasa_faces/helpers/picasa_faces_event.php
@@ -1,22 +1,37 @@
deactivate))
- {
- site_status::warning(
- t("The Picasa Faces module requires the Photo Annotation module. " .
- "Activate the Photo Annotation module now",
- array("url" => url::site("admin/modules"))),
- "picasa_faces_needs_photoannotation");
- }
- else
- {
- site_status::clear("picasa_faces_needs_photoannotation");
- }
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2010 Bharat Mediratta
+ *
+ * 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 Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class picasa_faces_event_Core {
+ static function module_change($changes) {
+ // See if the Photo Annotation module is installed,
+ // tell the user to install it if it isn't.
+ if (!module::is_active("photoannotation") || in_array("photoannotation", $changes->deactivate)) {
+ site_status::warning(
+ t("The Picasa Faces module requires the Photo Annotation module. " .
+ "Activate the Photo Annotation module now",
+ array("url" => url::site("admin/modules"))),
+ "picasa_faces_needs_photoannotation");
}
+ else {
+ site_status::clear("picasa_faces_needs_photoannotation");
+ }
+ }
}
+
+?>
diff --git a/3.0/modules/picasa_faces/helpers/picasa_faces_installer.php b/3.0/modules/picasa_faces/helpers/picasa_faces_installer.php
index 571626f3..5e728858 100644
--- a/3.0/modules/picasa_faces/helpers/picasa_faces_installer.php
+++ b/3.0/modules/picasa_faces/helpers/picasa_faces_installer.php
@@ -1,50 +1,63 @@
query(
+ "CREATE TABLE IF NOT EXISTS `picasa_faces` (
+ `id` int(9) NOT NULL auto_increment,
+ `face_id` varchar(16) NOT NULL,
+ `tag_id` int(9) NOT NULL,
+ `user_id` int(9) NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `face_id` (`face_id`,`id`)
+ ) DEFAULT CHARSET=utf8;"
+ );
- $db->query(
- "CREATE TABLE IF NOT EXISTS `picasa_faces` (
- `id` int(9) NOT NULL auto_increment,
- `face_id` varchar(16) NOT NULL,
- `tag_id` int(9) NOT NULL,
- `user_id` int(9) NOT NULL,
- PRIMARY KEY (`id`),
- KEY `face_id` (`face_id`,`id`)
- ) DEFAULT CHARSET=utf8;"
- );
+ // Set the module version number.
+ module::set_version("picasa_faces", 2);
+ }
- // Set the module version number.
- module::set_version("picasa_faces", 2);
+ static function upgrade($version) {
+ if ($version == 1) {
+ Database::instance()->query(
+ "ALTER TABLE `picasa_faces` ADD `user_id` int(9) NOT NULL"
+ );
+
+ module::set_version("picasa_faces", 2);
}
+ }
- static function upgrade($version)
- {
- if ($version == 1)
- {
- Database::instance()->query(
- "ALTER TABLE `picasa_faces` ADD `user_id` int(9) NOT NULL"
- );
+ static function deactivate() {
+ // Clear the require photo annototaion message when picasa faces is deactivated.
+ site_status::clear("picasa_faces_needs_photoannotation");
+ }
- module::set_version("picasa_faces", 2);
- }
- }
-
- static function deactivate()
- {
- // Clear the require photo annototaion message when picasa faces is deactivated.
- site_status::clear("picasa_faces_needs_photoannotation");
- }
-
- static function uninstall()
- {
- // Delete the face mapping table before uninstalling.
- $db = Database::instance();
- $db->query("DROP TABLE IF EXISTS {picasa_faces};");
- module::delete("picasa_faces");
- }
+ static function uninstall() {
+ // Delete the face mapping table before uninstalling.
+ $db = Database::instance();
+ $db->query("DROP TABLE IF EXISTS {picasa_faces};");
+ module::delete("picasa_faces");
+ }
}
+
+?>
diff --git a/3.0/modules/picasa_faces/helpers/picasa_faces_task.php b/3.0/modules/picasa_faces/helpers/picasa_faces_task.php
index e845b593..5413a1f6 100644
--- a/3.0/modules/picasa_faces/helpers/picasa_faces_task.php
+++ b/3.0/modules/picasa_faces/helpers/picasa_faces_task.php
@@ -1,312 +1,292 @@
callback("picasa_faces_task::import_faces")
+ ->name(t("Import faces from Picasa"))
+ ->description(t("Scan all albums for Picasa face data and add any faces that don't already exist"))
+ ->severity(log::SUCCESS));
+ }
-class picasa_faces_task_Core
-{
- static function available_tasks()
- {
- return array(Task_Definition::factory()
- ->callback("picasa_faces_task::import_faces")
- ->name(t("Import faces from Picasa"))
- ->description(t("Scan all albums for Picasa face data and add any faces that don't already exist"))
- ->severity(log::SUCCESS));
+ static function import_faces($task) {
+ if (!module::is_active("photoannotation")) {
+ $task->done = true;
+ $task->status = t("Photo Annotation module is inactive, no faces will be imported");
+ return;
}
- static function import_faces($task)
- {
- if (!module::is_active("photoannotation"))
- {
- $task->done = true;
- $task->status = t("Photo Annotation module is inactive, no faces will be imported");
- return;
- }
+ $start = microtime(true);
- $start = microtime(true);
+ // Figure out the total number of albums in the database.
+ // If this is the first run, also set last_id and completed to 0.
+ $total = $task->get("total");
+ if (empty($total)) {
+ $task->set("total", $total = count(ORM::factory("item")->where("type", "=", "album")->find_all()));
+ $task->set("last_id", 0);
+ $task->set("completed", 0);
+ $task->set("new_faces", 0);
+ $task->set("old_faces", 0);
+ }
+ $last_id = $task->get("last_id");
+ $completed = $task->get("completed");
+ $new_faces = $task->get("new_faces");
+ $old_faces = $task->get("old_faces");
- // Figure out the total number of albums in the database.
- // If this is the first run, also set last_id and completed to 0.
- $total = $task->get("total");
- if (empty($total))
- {
- $task->set("total", $total = count(ORM::factory("item")->where("type", "=", "album")->find_all()));
- $task->set("last_id", 0);
- $task->set("completed", 0);
- $task->set("new_faces", 0);
- $task->set("old_faces", 0);
- }
- $last_id = $task->get("last_id");
- $completed = $task->get("completed");
- $new_faces = $task->get("new_faces");
- $old_faces = $task->get("old_faces");
-
- // Try to find a contacts.xml file, and parse out the contents if it exists
- $contacts = null;
- $contactsXML = VARPATH . "albums/contacts.xml";
- if (file_exists($contactsXML))
- {
- $xml = simplexml_load_file($contactsXML);
- $contacts = $xml->contact;
- }
-
- // Check each album in the database to see if it has a .picasa.ini file on disk,
- // and extract any faces if it does.
- foreach (ORM::factory("item")
- ->where("id", ">", $last_id)
- ->where("type", "=", "album")
- ->find_all(100) as $albumItem)
- {
- $picasaFile = $albumItem->file_path()."/.picasa.ini";
- if (file_exists($picasaFile))
- {
- // Parse the .picasa.ini file and extract any faces
- $photosWithFaces = self::parsePicasaIni($picasaFile);
-
- // Build a mapping from photo filenames in this album to the items
- $photos = array();
- foreach ($albumItem->children() as $child)
- {
- if ($child->is_photo())
- {
- $photos[$child->name] = $child;
- }
- }
-
- // Iterate through all the photos with faces in them
- foreach ($photosWithFaces as $photoName => $faces)
- {
- // Find the item for this photo
- $photoItem = $photos[$photoName];
- if ($photoItem)
- {
- foreach ($faces as $faceId => $faceCoords)
- {
- $faceMapping = ORM::factory("picasa_face")->where("face_id", "=", $faceId)->find();
-
- // If we don't already have a mapping for this face, create one
- if (!$faceMapping->loaded())
- {
- $newTagId = self::getFaceMapping($faceId, $contacts);
-
- // Save the mapping from Picasa face id to tag id, so
- // faces will be grouped properly
- $faceMapping->face_id = $faceId;
- $faceMapping->tag_id = $newTagId;
- $faceMapping->user_id = 0;
- $faceMapping->save();
- }
-
- if ($faceMapping->user_id == 0)
- {
- $numTagsOnPhoto = ORM::factory("items_face")
- ->where("tag_id", "=", $faceMapping->tag_id)
- ->where("item_id", "=", $photoItem->id)
- ->count_all();
- }
- else
- {
- $numTagsOnPhoto = ORM::factory("items_user")
- ->where("user_id", "=", $faceMapping->user_id)
- ->where("item_id", "=", $photoItem->id)
- ->count_all();
- }
-
- // If this face tag isn't already on this photo, add it (we
- // assume a face should only ever appear once per photo)
- if ($numTagsOnPhoto == 0)
- {
- self::addNewFace($faceMapping, $faceCoords, $photoItem);
- $new_faces++;
- }
- else
- {
- $old_faces++;
- }
- }
- }
- }
- }
-
- $last_id = $albumItem->id;
- $completed++;
-
- if ($completed == $total || microtime(true) - $start > 1.5)
- {
- break;
- }
- }
-
- $task->set("completed", $completed);
- $task->set("last_id", $last_id);
- $task->set("new_faces", $new_faces);
- $task->set("old_faces", $old_faces);
-
- if ($total == $completed)
- {
- $task->done = true;
- $task->state = "success";
- $task->percent_complete = 100;
- }
- else
- {
- $task->percent_complete = round(100 * $completed / $total);
- }
-
- $task->status = t("%completed / %total albums scanned, %new_faces faces added, %old_faces faces unchanged",
- array("completed" => $completed, "total" => $total, "new_faces" => $new_faces, "old_faces" => $old_faces));
+ // Try to find a contacts.xml file, and parse out the contents if it exists
+ $contacts = null;
+ $contactsXML = VARPATH . "albums/contacts.xml";
+ if (file_exists($contactsXML)) {
+ $xml = simplexml_load_file($contactsXML);
+ $contacts = $xml->contact;
}
- static function getFaceMapping($faceId, $contacts)
- {
- $personTag = null;
+ // Check each album in the database to see if it has a .picasa.ini file on disk,
+ // and extract any faces if it does.
+ foreach (ORM::factory("item")
+ ->where("id", ">", $last_id)
+ ->where("type", "=", "album")
+ ->find_all(100) as $albumItem) {
+ $picasaFile = $albumItem->file_path()."/.picasa.ini";
+ if (file_exists($picasaFile)) {
+ // Parse the .picasa.ini file and extract any faces
+ $photosWithFaces = self::parsePicasaIni($picasaFile);
- // If we have a contacts.xml file, try to find the face id there
- if ($contacts != null)
- {
- foreach ($contacts as $contact)
- {
- if ($contact['id'] == $faceId)
- {
- // We found this face id in the contacts.xml. See if a tag already exists.
- $personTag = ORM::factory("tag")->where("name", "=", $contact['name'])->find();
-
- // If the tag doesn't exist already, add it
- if (!$personTag->loaded())
- {
- $personTag->name = $contact['name'];
- $personTag->save();
- }
-
- break;
- }
+ // Build a mapping from photo filenames in this album to the items
+ $photos = array();
+ foreach ($albumItem->children() as $child) {
+ if ($child->is_photo()) {
+ $photos[$child->name] = $child;
}
}
- // We either didn't find the face in contacts.xml, or we don't have contacts.xml.
- // Add the face using a generic name.
- if ($personTag == null)
- {
- // Find an unused "Picasa x" tag
- $personID = 0;
- $personName = "";
- do
- {
- $personID++;
- $personName = "Picasa ".$personID;
- $personTag = ORM::factory("tag")->where("name", "=", $personName)->find();
- } while ($personTag->loaded());
+ // Iterate through all the photos with faces in them
+ foreach ($photosWithFaces as $photoName => $faces) {
+ // Find the item for this photo
+ $photoItem = $photos[$photoName];
+ if ($photoItem) {
+ foreach ($faces as $faceId => $faceCoords) {
+ $faceMapping = ORM::factory("picasa_face")->where("face_id", "=", $faceId)->find();
- // We found an open name, save it so we can get the id
- $personTag->name = $personName;
+ // If we don't already have a mapping for this face, create one
+ if (!$faceMapping->loaded()) {
+ $newTagId = self::getFaceMapping($faceId, $contacts);
+
+ // Save the mapping from Picasa face id to tag id, so
+ // faces will be grouped properly
+ $faceMapping->face_id = $faceId;
+ $faceMapping->tag_id = $newTagId;
+ $faceMapping->user_id = 0;
+ $faceMapping->save();
+ }
+
+ if ($faceMapping->user_id == 0) {
+ $numTagsOnPhoto = ORM::factory("items_face")
+ ->where("tag_id", "=", $faceMapping->tag_id)
+ ->where("item_id", "=", $photoItem->id)
+ ->count_all();
+ }
+ else {
+ $numTagsOnPhoto = ORM::factory("items_user")
+ ->where("user_id", "=", $faceMapping->user_id)
+ ->where("item_id", "=", $photoItem->id)
+ ->count_all();
+ }
+
+ // If this face tag isn't already on this photo, add it (we
+ // assume a face should only ever appear once per photo)
+ if ($numTagsOnPhoto == 0) {
+ self::addNewFace($faceMapping, $faceCoords, $photoItem);
+ $new_faces++;
+ }
+ else {
+ $old_faces++;
+ }
+ }
+ }
+ }
+ }
+
+ $last_id = $albumItem->id;
+ $completed++;
+
+ if ($completed == $total || microtime(true) - $start > 1.5) {
+ break;
+ }
+ }
+
+ $task->set("completed", $completed);
+ $task->set("last_id", $last_id);
+ $task->set("new_faces", $new_faces);
+ $task->set("old_faces", $old_faces);
+
+ if ($total == $completed) {
+ $task->done = true;
+ $task->state = "success";
+ $task->percent_complete = 100;
+ }
+ else {
+ $task->percent_complete = round(100 * $completed / $total);
+ }
+
+ $task->status = t("%completed / %total albums scanned, %new_faces faces added, %old_faces faces unchanged",
+ array("completed" => $completed, "total" => $total, "new_faces" => $new_faces, "old_faces" => $old_faces));
+ }
+
+ static function getFaceMapping($faceId, $contacts) {
+ $personTag = null;
+
+ // If we have a contacts.xml file, try to find the face id there
+ if ($contacts != null) {
+ foreach ($contacts as $contact) {
+ if ($contact['id'] == $faceId) {
+ // We found this face id in the contacts.xml. See if a tag already exists.
+ $personTag = ORM::factory("tag")->where("name", "=", $contact['name'])->find();
+
+ // If the tag doesn't exist already, add it
+ if (!$personTag->loaded()) {
+ $personTag->name = $contact['name'];
$personTag->save();
- }
+ }
- return $personTag->id;
+ break;
+ }
+ }
}
- static function addNewFace($faceMapping, $faceCoords, $photoItem)
- {
- // Calculate the face coordinates. Picasa stores them as 0-65535, and we remap
- // that to the resize dimensions.
- $left = (int)(($photoItem->resize_width * $faceCoords["left"]) / 65535);
- $top = (int)(($photoItem->resize_height * $faceCoords["top"]) / 65535);
- $right = (int)(($photoItem->resize_width * $faceCoords["right"]) / 65535);
- $bottom = (int)(($photoItem->resize_height * $faceCoords["bottom"]) / 65535);
+ // We either didn't find the face in contacts.xml, or we don't have contacts.xml.
+ // Add the face using a generic name.
+ if ($personTag == null) {
+ // Find an unused "Picasa x" tag
+ $personID = 0;
+ $personName = "";
+ do {
+ $personID++;
+ $personName = "Picasa ".$personID;
+ $personTag = ORM::factory("tag")->where("name", "=", $personName)->find();
+ } while ($personTag->loaded());
- if ($faceMapping->user_id == 0)
- {
- // Add the photo to this tag
- $tag = ORM::factory("tag")->where("id", "=", $faceMapping->tag_id)->find();
- $tag->add($photoItem);
- $tag->count++;
- $tag->save();
-
- // Add the face
- $newFace = ORM::factory("items_face");
- $newFace->tag_id = $faceMapping->tag_id;
- $newFace->item_id = $photoItem->id;
- $newFace->x1 = $left;
- $newFace->y1 = $top;
- $newFace->x2 = $right;
- $newFace->y2 = $bottom;
- $newFace->description = "";
- $newFace->save();
- }
- else
- {
- // Add the face
- $newFace = ORM::factory("items_user");
- $newFace->user_id = $faceMapping->user_id;
- $newFace->item_id = $photoItem->id;
- $newFace->x1 = $left;
- $newFace->y1 = $top;
- $newFace->x2 = $right;
- $newFace->y2 = $bottom;
- $newFace->description = "";
- $newFace->save();
- }
+ // We found an open name, save it so we can get the id
+ $personTag->name = $personName;
+ $personTag->save();
}
- static function parsePicasaIni($filePath)
- {
- // It would be nice to use parse_ini_file here, but the parens used with the rect64 values break it
- $ini_lines = file($filePath);
+ return $personTag->id;
+ }
- $curFilename = "";
+ static function addNewFace($faceMapping, $faceCoords, $photoItem) {
+ // Calculate the face coordinates. Picasa stores them as 0-65535, and we remap
+ // that to the resize dimensions.
+ $left = (int)(($photoItem->resize_width * $faceCoords["left"]) / 65535);
+ $top = (int)(($photoItem->resize_height * $faceCoords["top"]) / 65535);
+ $right = (int)(($photoItem->resize_width * $faceCoords["right"]) / 65535);
+ $bottom = (int)(($photoItem->resize_height * $faceCoords["bottom"]) / 65535);
- $photosWithFaces = array();
+ if ($faceMapping->user_id == 0) {
+ // Add the photo to this tag
+ $tag = ORM::factory("tag")->where("id", "=", $faceMapping->tag_id)->find();
+ $tag->add($photoItem);
+ $tag->count++;
+ $tag->save();
- foreach ($ini_lines as $ini_line)
- {
- // Trim off any whitespace at the ends
- $ini_line = trim($ini_line);
-
- if ($ini_line[0] == '[')
- {
- // If this line starts with [ it's a filename, strip off the brackets
- $curFilename = substr($ini_line, 1, -1);
- }
- else
- {
- // If this isn't a filename, it must be data for a file, get the key/value pair
- $photoData = explode("=", $ini_line);
-
- if ($photoData[0] == "faces")
- {
- // If it's face data, break it up by face
- $faces = explode(";", $photoData[1]);
-
- $photoFaces = array();
-
- foreach ($faces as $face)
- {
- // Split a face into the rectangle and face id
- $splitface = explode(",", $face);
-
- $hexrect = substr($splitface[0], 7, -1);
- // We need a string with 16 chars. Fill up with zeros from left.
- $hexrect = str_pad($hexrect, 16, "0", STR_PAD_LEFT);
- $person = $splitface[1];
-
- // The rectangle is 4 4-character hex values
- $left = hexdec(substr($hexrect,0,4));
- $top = hexdec(substr($hexrect,4,4));
- $right = hexdec(substr($hexrect,8,4));
- $bottom = hexdec(substr($hexrect,12,4));
-
- $facePos = array("left" => $left,
- "top" => $top,
- "right" => $right,
- "bottom" => $bottom);
-
- $photoFaces[$person] = $facePos;
- }
-
- $photosWithFaces[$curFilename] = $photoFaces;
- }
- }
- }
-
- return $photosWithFaces;
+ // Add the face
+ $newFace = ORM::factory("items_face");
+ $newFace->tag_id = $faceMapping->tag_id;
+ $newFace->item_id = $photoItem->id;
+ $newFace->x1 = $left;
+ $newFace->y1 = $top;
+ $newFace->x2 = $right;
+ $newFace->y2 = $bottom;
+ $newFace->description = "";
+ $newFace->save();
}
+ else {
+ // Add the face
+ $newFace = ORM::factory("items_user");
+ $newFace->user_id = $faceMapping->user_id;
+ $newFace->item_id = $photoItem->id;
+ $newFace->x1 = $left;
+ $newFace->y1 = $top;
+ $newFace->x2 = $right;
+ $newFace->y2 = $bottom;
+ $newFace->description = "";
+ $newFace->save();
+ }
+ }
+
+ static function parsePicasaIni($filePath) {
+ // It would be nice to use parse_ini_file here, but the parens used with the rect64 values break it
+ $ini_lines = file($filePath);
+
+ $curFilename = "";
+
+ $photosWithFaces = array();
+
+ foreach ($ini_lines as $ini_line) {
+ // Trim off any whitespace at the ends
+ $ini_line = trim($ini_line);
+
+ if ($ini_line[0] == '[') {
+ // If this line starts with [ it's a filename, strip off the brackets
+ $curFilename = substr($ini_line, 1, -1);
+ }
+ else {
+ // If this isn't a filename, it must be data for a file, get the key/value pair
+ $photoData = explode("=", $ini_line);
+
+ if ($photoData[0] == "faces") {
+ // If it's face data, break it up by face
+ $faces = explode(";", $photoData[1]);
+
+ $photoFaces = array();
+
+ foreach ($faces as $face) {
+ // Split a face into the rectangle and face id
+ $splitface = explode(",", $face);
+
+ $hexrect = substr($splitface[0], 7, -1);
+ // We need a string with 16 chars. Fill up with zeros from left.
+ $hexrect = str_pad($hexrect, 16, "0", STR_PAD_LEFT);
+ $person = $splitface[1];
+
+ // The rectangle is 4 4-character hex values
+ $left = hexdec(substr($hexrect,0,4));
+ $top = hexdec(substr($hexrect,4,4));
+ $right = hexdec(substr($hexrect,8,4));
+ $bottom = hexdec(substr($hexrect,12,4));
+
+ $facePos = array("left" => $left,
+ "top" => $top,
+ "right" => $right,
+ "bottom" => $bottom);
+
+ $photoFaces[$person] = $facePos;
+ }
+
+ $photosWithFaces[$curFilename] = $photoFaces;
+ }
+ }
+ }
+
+ return $photosWithFaces;
+ }
}
?>
diff --git a/3.0/modules/picasa_faces/helpers/picasa_faces_task.php.bak b/3.0/modules/picasa_faces/helpers/picasa_faces_task.php.bak
deleted file mode 100644
index 7bdff7a7..00000000
--- a/3.0/modules/picasa_faces/helpers/picasa_faces_task.php.bak
+++ /dev/null
@@ -1,313 +0,0 @@
-callback("picasa_faces_task::import_faces")
- ->name(t("Import faces from Picasa"))
- ->description(t("Scan all albums for Picasa face data and add any faces that don't already exist"))
- ->severity(log::SUCCESS));
- }
-
- static function import_faces($task)
- {
- if (!module::is_active("photoannotation"))
- {
- $task->done = true;
- $task->status = t("Photo Annotation module is inactive, no faces will be imported");
- return;
- }
-
- $start = microtime(true);
-
- // Figure out the total number of albums in the database.
- // If this is the first run, also set last_id and completed to 0.
- $total = $task->get("total");
- if (empty($total))
- {
- $task->set("total", $total = count(ORM::factory("item")->where("type", "=", "album")->find_all()));
- $task->set("last_id", 0);
- $task->set("completed", 0);
- $task->set("new_faces", 0);
- $task->set("old_faces", 0);
- }
-
- $last_id = $task->get("last_id");
- $completed = $task->get("completed");
- $new_faces = $task->get("new_faces");
- $old_faces = $task->get("old_faces");
-
- // Try to find a contacts.xml file, and parse out the contents if it exists
- $contacts = null;
- $contactsXML = VARPATH . "albums/contacts.xml";
- if (file_exists($contactsXML))
- {
- $xml = simplexml_load_file($contactsXML);
- $contacts = $xml->contact;
- }
-
- // Check each album in the database to see if it has a .picasa.ini file on disk,
- // and extract any faces if it does.
- foreach (ORM::factory("item")
- ->where("id", ">", $last_id)
- ->where("type", "=", "album")
- ->find_all(100) as $albumItem)
- {
- $picasaFile = $albumItem->file_path()."/.picasa.ini";
- if (file_exists($picasaFile))
- {
- // Parse the .picasa.ini file and extract any faces
- $photosWithFaces = self::parsePicasaIni($picasaFile);
-
- // Build a mapping from photo filenames in this album to the items
- $photos = array();
- foreach ($albumItem->children() as $child)
- {
- if ($child->is_photo())
- {
- $photos[$child->name] = $child;
- }
- }
-
- // Iterate through all the photos with faces in them
- foreach ($photosWithFaces as $photoName => $faces)
- {
- // Find the item for this photo
- $photoItem = $photos[$photoName];
- if ($photoItem)
- {
- foreach ($faces as $faceId => $faceCoords)
- {
- $faceMapping = ORM::factory("picasa_face")->where("face_id", "=", $faceId)->find();
-
- // If we don't already have a mapping for this face, create one
- if (!$faceMapping->loaded())
- {
- $newTagId = self::getFaceMapping($faceId, $contacts);
-
- // Save the mapping from Picasa face id to tag id, so
- // faces will be grouped properly
- $faceMapping->face_id = $faceId;
- $faceMapping->tag_id = $newTagId;
- $faceMapping->user_id = 0;
- $faceMapping->save();
- }
-
- if ($faceMapping->user_id == 0)
- {
- $numTagsOnPhoto = ORM::factory("items_face")
- ->where("tag_id", "=", $faceMapping->tag_id)
- ->where("item_id", "=", $photoItem->id)
- ->count_all();
- }
- else
- {
- $numTagsOnPhoto = ORM::factory("items_user")
- ->where("user_id", "=", $faceMapping->user_id)
- ->where("item_id", "=", $photoItem->id)
- ->count_all();
- }
-
- // If this face tag isn't already on this photo, add it (we
- // assume a face should only ever appear once per photo)
- if ($numTagsOnPhoto == 0)
- {
- self::addNewFace($faceMapping, $faceCoords, $photoItem);
- $new_faces++;
- }
- else
- {
- $old_faces++;
- }
- }
- }
- }
- }
-
- $last_id = $albumItem->id;
- $completed++;
-
- if ($completed == $total || microtime(true) - $start > 1.5)
- {
- break;
- }
- }
-
- $task->set("completed", $completed);
- $task->set("last_id", $last_id);
- $task->set("new_faces", $new_faces);
- $task->set("old_faces", $old_faces);
-
- if ($total == $completed)
- {
- $task->done = true;
- $task->state = "success";
- $task->percent_complete = 100;
- }
- else
- {
- $task->percent_complete = round(100 * $completed / $total);
- }
-
- $task->status = t("%completed / %total albums scanned, %new_faces faces added, %old_faces faces unchanged",
- array("completed" => $completed, "total" => $total, "new_faces" => $new_faces, "old_faces" => $old_faces));
- }
-
- static function getFaceMapping($faceId, $contacts)
- {
- $personTag = null;
-
- // If we have a contacts.xml file, try to find the face id there
- if ($contacts != null)
- {
- foreach ($contacts as $contact)
- {
- if ($contact['id'] == $faceId)
- {
- // We found this face id in the contacts.xml. See if a tag already exists.
- $personTag = ORM::factory("tag")->where("name", "=", $contact['name'])->find();
-
- // If the tag doesn't exist already, add it
- if (!$personTag->loaded())
- {
- $personTag->name = $contact['name'];
- $personTag->save();
- }
-
- break;
- }
- }
- }
-
- // We either didn't find the face in contacts.xml, or we don't have contacts.xml.
- // Add the face using a generic name.
- if ($personTag == null)
- {
- // Find an unused "Picasa x" tag
- $personID = 0;
- $personName = "";
- do
- {
- $personID++;
- $personName = "Picasa ".$personID;
- $personTag = ORM::factory("tag")->where("name", "=", $personName)->find();
- } while ($personTag->loaded());
-
- // We found an open name, save it so we can get the id
- $personTag->name = $personName;
- $personTag->save();
- }
-
- return $personTag->id;
- }
-
- static function addNewFace($faceMapping, $faceCoords, $photoItem)
- {
- // Calculate the face coordinates. Picasa stores them as 0-65535, and we remap
- // that to the resize dimensions.
- $left = (int)(($photoItem->resize_width * $faceCoords["left"]) / 65535);
- $top = (int)(($photoItem->resize_height * $faceCoords["top"]) / 65535);
- $right = (int)(($photoItem->resize_width * $faceCoords["right"]) / 65535);
- $bottom = (int)(($photoItem->resize_height * $faceCoords["bottom"]) / 65535);
-
- if ($faceMapping->user_id == 0)
- {
- // Add the photo to this tag
- $tag = ORM::factory("tag")->where("id", "=", $faceMapping->tag_id)->find();
- $tag->add($photoItem);
- $tag->count++;
- $tag->save();
-
- // Add the face
- $newFace = ORM::factory("items_face");
- $newFace->tag_id = $faceMapping->tag_id;
- $newFace->item_id = $photoItem->id;
- $newFace->x1 = $left;
- $newFace->y1 = $top;
- $newFace->x2 = $right;
- $newFace->y2 = $bottom;
- $newFace->description = "";
- $newFace->save();
- }
- else
- {
- // Add the face
- $newFace = ORM::factory("items_user");
- $newFace->user_id = $faceMapping->user_id;
- $newFace->item_id = $photoItem->id;
- $newFace->x1 = $left;
- $newFace->y1 = $top;
- $newFace->x2 = $right;
- $newFace->y2 = $bottom;
- $newFace->description = "";
- $newFace->save();
- }
- }
-
- static function parsePicasaIni($filePath)
- {
- // It would be nice to use parse_ini_file here, but the parens used with the rect64 values break it
- $ini_lines = file($filePath);
-
- $curFilename = "";
-
- $photosWithFaces = array();
-
- foreach ($ini_lines as $ini_line)
- {
- // Trim off any whitespace at the ends
- $ini_line = trim($ini_line);
-
- if ($ini_line[0] == '[')
- {
- // If this line starts with [ it's a filename, strip off the brackets
- $curFilename = substr($ini_line, 1, -1);
- }
- else
- {
- // If this isn't a filename, it must be data for a file, get the key/value pair
- $photoData = explode("=", $ini_line);
-
- if ($photoData[0] == "faces")
- {
- // If it's face data, break it up by face
- $faces = explode(";", $photoData[1]);
-
- $photoFaces = array();
-
- foreach ($faces as $face)
- {
- // Split a face into the rectangle and face id
- $splitface = explode(",", $face);
-
- $hexrect = substr($splitface[0], 7, -1);
- // We need a string with 16 chars. Fill up with zeros from left.
- $hexrect = str_pad($hexrect, 16, "0", STR_PAD_LEFT);
- $person = $splitface[1];
-
- // The rectangle is 4 4-character hex values
- $left = hexdec(substr($hexrect,0,4));
- $top = hexdec(substr($hexrect,4,4));
- $right = hexdec(substr($hexrect,8,4));
- $bottom = hexdec(substr($hexrect,12,4));
-
- $facePos = array("left" => $left,
- "top" => $top,
- "right" => $right,
- "bottom" => $bottom);
-
- $photoFaces[$person] = $facePos;
- }
-
- $photosWithFaces[$curFilename] = $photoFaces;
- }
- }
- }
-
- return $photosWithFaces;
- }
-}
-
-?>
diff --git a/3.0/modules/picasa_faces/models/picasa_face.php b/3.0/modules/picasa_faces/models/picasa_face.php
index f70cbc8a..12dd6f50 100644
--- a/3.0/modules/picasa_faces/models/picasa_face.php
+++ b/3.0/modules/picasa_faces/models/picasa_face.php
@@ -1,5 +1,22 @@