Skip to content

Instantly share code, notes, and snippets.

@timlinux
Forked from lovasoa/README.markdown
Created October 10, 2011 21:33
Show Gist options
  • Save timlinux/1276613 to your computer and use it in GitHub Desktop.
Save timlinux/1276613 to your computer and use it in GitHub Desktop.
The dezoomify script is capable of grabbing images from a webpage containing a Zoomify viewer and automatically stitching the images with javascript and the HTML5 <canvas> element.

#Reassemble tiles of a zoomify-powered image

This script makes one downloadable image from an image viewable via a flash zoomify interface.

Input : the URL of a site containing a zoomify viewer. Output : An image that you can download (in Firefox).

#Try it If you are not interested in the source code and just want to assemble tiles of (dezoomify) a zoomify-powered image, go there : unzoomify an image

#Programming Languages The aim of the script is to do as much as possible in Javascript (with the HTML5 tag), and only the network-related stuffs on the server side (in this case, PHP).

#Wikimedia This script on wikimedia : Zoomify in the help about zoomable Images on wikimedia

#GPL

Copyright © 2011 Lovasoa

This file is part of Dezoomify.

Dezoomify 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.

Dezoomify 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 Dezoomify; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*/

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" >
<!--Le dézoumistificateur
The dezoomify script is capable of grabbing images from a webpage containing a Zoomify viewer and automatically stitching the images with javascript and the HTML5 <canvas> element.
This script is inspired by the source code of http://toolserver.org/~kolossos/image/zoomify.php
but instead of using a table to display the image, it uses javascript, and the html5 <canvas> element
-->
<head>
<title>Dezoomify</title>
<style type="text/css">
body {
margin:0;
padding:0;
background-color:black;
}
#status {
position:fixed;
top:25%;
left:30%;
width:40%;
min-height:20%;
background-color:rgba(40,40,40,0.9);
-moz-border-radius:16px;
-webkit-border-radius:16px;
}
form {
margin-top:15%;
padding-left:7%;
width:86%;
}
input#url {
width:300px;
max-width:100%;
background:-moz-linear-gradient(90deg, #fff, #eee); /* Firefox */
background:-webkit-gradient(linear, left top, left bottom, from(#eee), to(#fff), color-stop(0.2, #fff)); /* Webkit */
-moz-border-radius:3px;
-webkit-border-radius:3px;
-moz-box-shadow:0 0 3px #aaa;
-webkit-box-shadow:0 0 3px #aaa;
}
#percent {
color:white;
font-size:4em;
text-align:center;
}
#progressbar {
width:0px;
background-color:red;
height:7px;
}
#error {
display:none;
padding:7px;
}
</style>
<script type="text/javascript" src="dezoomify.js" ></script>
</head>
<body>
<div id="dezoomifiedImage"></div>
<div id="status">
<form onsubmit="javascript:dezoomify()" action="#">
<p>
<input type='text' id='url' value="URL of the webpage containing a zoomify viewer" onfocus="this.value=''" />
<input type='submit' />
</p>
</form>
<p id="percent"></p>
<p id="progressbar"></p>
<div id="error"><p style='color:red;'>Error : Unable to extract informations from the given file !</p>
Try to extract the zoomifyImagePath in the webpage containing the zoomify viewer on your own , and reload this page with the path you found as parameter. Search 'zoomifyImagePath' in the real source code of the page (the one you can get with firebug in firefox, or the web inspector in Safari/Chrome
<br /><br />Exemple : http://ophir.lojkine.free.fr/dezoomify/dezoomify.php?path=http://images.famsf.org/Zoom/7822312331480020/
</div>
</div>
</body>
</html>
function dezoomify() {
//Fetches some informations about the image, and then draw it
var url = encodeURIComponent(document.getElementById("url").value);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var xml = xhr.responseXML;
path = xml.firstChild.getAttribute("path");
var infos = xml.getElementsByTagName("IMAGE_PROPERTIES")[0];
if (!infos) {
document.getElementById("error").style.display = "block";
console.log(xhr.responseText);
}
width = parseInt(infos.getAttribute("WIDTH"));
height = parseInt(infos.getAttribute("HEIGHT"));
tileSize = parseInt(infos.getAttribute("TILESIZE"));
numTiles = parseInt(infos.getAttribute("NUMTILES"));
remove(document.forms[0]);
drawImage();
} else {
error = document.getElementById("error");
error.innerHTML = "Error : Unable to join the server. Error code " + xhr.status;
error.style.display = "block";
}
}
document.getElementById("progressbar").style.width = 25 * xhr.readyState + "%";
};
xhr.open("GET", "dezoomify.php?url=" + url, true);
xhr.send(null);
}
function remove(el) {
el.parentNode.removeChild(el);
}
function addTile(url, x, y) {
//Demande une partie de l'image au serveur, et l'affiche lorsqu'elle est reçue
var i = document.createElement("img");
i.onload = function () {
ctx.drawImage(i, x, y);
loaded++;
}
i.src = url;
}
function loadEnd() {
//Fonction appelée lorsque l'image est entièrement chargée
clearInterval(timer);
var status = document.getElementById("status");
status.parentNode.removeChild(status);
}
function changeSize() {
//Ajuste la taille de l'image, pour qu'elle soit en taille de base, ou ajustée à la largeur ou la hauteur de la page
if (typeof(fit) == "undefined") {
//Fit page width
fit = "width";
canvas.style.width = window.innerWidth + "px";
canvas.style.height = window.innerWidth / width * height + "px";
} else if (fit == "height") {
//Max zoom
fit = undefined;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
} else if (fit == "width") {
//Fit page height
fit = "height";
canvas.style.height = window.innerHeight + "px";
canvas.style.width = window.innerHeight / height * width + "px";
}
}
function findZoom(size) {
//Fonction de BG
return Math.floor(Math.log(size) / Math.log(2) - 7);
}
function drawImage() {
//Tout le code. On devrait peut-être le couper en plusieurs fonctions
canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
canvas.onclick = changeSize;
document.getElementById("dezoomifiedImage").appendChild(canvas);
changeSize("width");
console.log(width, height)
console.log((width > height) ? findZoom(width) : findZoom(height))
zoom = (width > height) ? findZoom(width) : findZoom(height);
var nbrTilesX = Math.ceil(width / tileSize);
var nbrTilesY = Math.ceil(height / tileSize);
loaded = 0;
totalTiles = nbrTilesX * nbrTilesY; //Total number of tiles to load
var skippedTiles = numTiles - totalTiles;
var tileGroup = Math.floor(skippedTiles / 256);
var tileGroupCounter = skippedTiles % 256;
var x, y;
for (y = 0; y < nbrTilesY; y++) {
for (x = 0; x < nbrTilesX; x++) {
if (tileGroupCounter >= 256) {
tileGroup++;
tileGroupCounter = 0;
}
tileGroupCounter++;
var url = path + "/TileGroup" + tileGroup + "/" + zoom + "-" + x + "-" + y + ".jpg";
addTile(url, x * tileSize, y * tileSize);
}
}
timer = setInterval(function () {
document.getElementById("percent").innerHTML = Math.floor(100 * loaded / totalTiles) + " %";
document.getElementById("progressbar").style.width = 100 * loaded / totalTiles + "%";
if (loaded == totalTiles) {
loadEnd();
}
}, 200);
}
<?php
ini_set("display_errors",0);//Comment this line to debug the script
header('Content-Type: text/xml');//The script returns xml and not html
function url_to_absolute ($url, $path) {
//Returns the absolute path to an URL and a path
//If the path is in fact an url, return it
if (preg_match("#^[a-zA-Z0-9]+://#i", $path)) return $path;
if ($path[0] == '/'){//If the path is relative to the base server
return preg_replace ("#([a-zA-Z0-9]+://[^/]+)(/.*)?#i", "$1/".$path, $url);
}else {
return preg_replace ("#([a-zA-Z0-9]+://[^/]+(/[^$\.\?&]*)?)(/.*?)?$#i", "$1/".$path, $url);
}
}
function zoomifyPath ($url){
//Extract the path to the zoomify folder from any page containing a Zoomify viewer
$html = file_get_contents($url);
if ($html === FALSE){//If an error occured
return $url;//We assume that the provided url was the zoomifyImagePath
}
preg_match ( '/zoomifyImagePath=([^\'"&]*)[\'"&]/i', $html , $addr );
//var_dump($addr);
return url_to_absolute ($url, $addr[1]);
}
if (isset($_GET['url'])){
$url = addslashes(rawurldecode($_GET['url']));
$path = zoomifyPath ($url);
}elseif (isset($_GET["path"])){
$path=addslashes(rawurldecode($_GET["path"]));
}else {
echo "<form method='get' action='dezoomify.php'>
<p>
<label for='url'>URL of the webpage containing a Zoomify viewer :</label>
<input type='text' name='url' id='url' size='100' />
<input type='submit' />
</p>";
}
$xml = file_get_contents($path."/ImageProperties.xml");
echo "<?xml version=\"1.0\"?>\n";
echo "
<infos path='$path'>
$xml
</infos>
";
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment