Advanced Thumbnail Creator

© Жупаненко Андрей
research@zhupanenko.com
research.zhupanenko.com/atc

1 Задача

Работая с новостными лентами или же просто с информацией, содержащей графические изображения, довольно часто возникает потребность генерации картинок-превью. На первый взгляд нет ничего проще чем создать уменьшенное изображение произвольного рисунка или фотографии. Однако оказывается и в этой области есть где развернуться.

2 Существующие решения

Есть несколько способов решения данной задачи:

  • 1. Использование оригинального изображения в качестве превью путем его уменьшения свойствами тега <img>.
  • 2. Уменьшение размеров изображения при помощи функций imagecopyresampled(), imagecopyresized() библиотеки GD.
  • 3. Выделение центральной области изображения и ее последующее преобразование функциями библиотеки GD.
  • 4. Создание превью при помощи графических приложений на локальной машине и последующая загрузка на сервер.
  • Очевидное преимущество первых трех методов - полная автоматизация процесса. Недостатки: в первом случае изображение загружается в оригинальном размере (рис. 2а), во втором - в превью не сохраняются оригинальные пропорции изображения (рис. 2б), в третьем - центральная часть изображения не всегда является "значащей" (рис. 2в).

    Четвертый способ генерации превью дает необходимые результаты (рис. 2г), но добавляет лишние хлопоты при переключении между приложениями, возникает необходимость загрузки двух файлов вместо одного (в лучшем случае).

    Figure 1 - Initial image

    Рисунок 1 - Исходное изображение

    Рисунок 2а - Результаты генерации превью а)
    Рисунок 2б - Результаты генерации превью б)
    Рисунок 2в - Результаты генерации превью в)
    Рисунок 2г - Результаты генерации превью г)

    Рисунок 2 - Результаты генерации превью (70x70)

    3 Решение

    Суть метода - автоматическое создание превью с помощью php-скрипта посредством ручного выделения "значащей" области.

    4 Используемые технологии

    PHP, Javascript, DOM, CSS, HTML

    5 Кросс-браузерность

    Internet Explorer 6.0,7.0; FireFox 1.0,2.0; Opera 9.0; Safari 2.0;

    6 Входные и выходные параметры

    Входные параметры:

    1. $_GET[filename] - строка, определяющая имя файла и путь к нему относительно корневого каталога на сервере. Переменная $_GET[filename] должна быть предварительно закодирована функцией urlencode();
    2. $_GET[thumbwidth] - предустановленная ширина превью изображения. Если этот параметр равен "0" или не определен, ширина превью определяется в зависимости от выбранной области.
    3. $_GET[thumbheight] - предустановленная высота превью изображения. Если этот параметр равен "0" или не определен, высота превью определяется в зависимости от выбранной области.

    Выходные параметры:

    1. 1. Превью изображения на странице браузера.
    2. 2. Файл-превью типа JPEG, находящийся в том же каталоге что и исходное изображение.

    7 Реализация

    Разработанный программный комплекс состоит из двух файлов.

    1. thumbcreate.js - набор функций для работы с выделяемой областью и функции подготовки генерации изображения.
    2. thumbcreate.php - содержит функцию генерации превью, блок отображения рабочей области и форму ввода-вывода параметров превью.

    7.1. Описание функций модуля thumbcreate.js.

    //initialization
    function init()
    {
    	document.getElementById("image").onclick=mouseHandler;
    	document.getElementById("image").onmousemove=mouseHandler;
    	document.getElementById('th_w').value=thumbWidth;
    	document.getElementById('th_h').value=thumbHeight;
    }
    
    //mouse handler
    function mouseHandler(mouseEvent)
    {
    	if (!mouseEvent) mouseEvent = window.event;
    	if (mouseEvent.button == 2) return;
    	var element = (mouseEvent.target)?mouseEvent.target:mouseEvent.srcElement;
    
    //for a clique we begin to draw a selection rectangle
    	if (mouseEvent.type=="click")
    	{
    	var x = mouseEvent.clientX - document.getElementById("image").offsetLeft;
    	var at = mouseEvent.clientY - document.getElementById("image").offsetTop;
    	pointSet(x,y);
    	rectangleDraw('area');
    	};
    
    //draw the selection region during mouse motion
    	if (mouseEvent.type=="mousemove")
    	{
    	.
    	}
    }
    
    //setting coordinates for top left and right bottom corner
    function pointSet(x,y)
    {
    	if (!ptype)
    	{
    	x1=x+document.body.scrollLeft;
    	y1=y+document.body.scrollTop;
    	rectangleHide('area');
    	inputUpdate();
    	}
    	else
    	{
    	x2=x+document.body.scrollLeft;
    	y2=y+document.body.scrollTop;
    	pointCorrect();
    	inputUpdate();
    	}
    	ptype = !ptype;
    }
    
    //correcting TL BR coordinates if they are switched
    function pointCorrect(x1c,y1c,x2c,y2c)
    {
    	.
    }
    
    //rectangle drawing (x1,y1); (x2,y2)
    function rectangleDraw(rectId)
    {
    	.
    }
    
    // rectangle drawing from input fields
    function rectangleDrawInput(rectId)
    {
    .
    }
    
    //rectangle hiding
    function rectangleHide(rectId)
    {
    	.
    }
    
    //input fields update functions
    function inputUpdate()
    {
    .
    }
    
    function inputWidthUpdate()
    {
    	.
    };
    
    function inputHeightUpdate()
    {
    	.
    };
    
    function inputXYUpdate()
    {
    	.
    };
    
    //prepare for thumbnail generation
    function generateImageThumb()
    {
    	var previewclass='preview';
    	var previewimage='/preview.gif';	
    
    	var links=document.getElementsByTagName('a');
    	var prevlinks=new Array();
    	var c=0;
    	
    	var previewTest = new RegExp("(^|s)" + previewclass + "(s|$)");
    
    	for(I=0; I<links.length; I++)
    	{
    	if (previewTest.test(links[I].className))
    	 prevlinks[c]=links[I]; c++; }
    	}
    
    	for(I=0; I<prevlinks.length; I++)
    	{
    
    	var newa=document.createElement('a');
    	newa.style.textDecoration="none";
    
    	var newbutton=document.createElement('input');
    	newbutton.type="button";
    	newbutton.value="Generate Thumbnail"
    
    	newa.appendChild(newbutton);
    	newa.href="#";
    
    	var newbr=document.createElement('br');
    	newa.appendChild(newbr);
    
    	newa.onclick=function()
    		{
    	if(this.getElementsByTagName('img')[0])
    	this.removeChild(this.getElementsByTagName('img')[0]);
    
    	var newimg=document.createElement('img');
    	newimg.style.border="0";
    	newimg.vspace="10";
    	this.appendChild(newimg);
    
    	var rand=parseInt(1000*Math.random());
    	newimg.src="?action=generate&r="+rand+"&x1="+document.getElementById('x1_inp').value+
    	"&y1="+document.getElementById('y1_inp').value+"&x2="+document.getElementById('x2_inp').value+
    	"&y2="+document.getElementById('y2_inp').value+"&w="+document.getElementById('th_w').value+
    	"&h="+document.getElementById('th_h').value+"&fn="+document.getElementById('fileName').value;
    
    	return false;
    		}
    
    	prevlinks[I].parentNode.insertBefore(newa,prevlinks[I].nextSibling);
    	}
    
    }	
    
    //initialization
    window.onload=function()
    {
    	init();
    	generateImageThumb();
    }

    7.2. Описание функций модуля thumbcreate.php.

    <?php
    	if (!$_GET[thumbwidth]) $_GET[thumbwidth]=0;
    	if (!$_GET[thumbheight]) $_GET[thumbheight]=0;
    
    //thumbnail creation function
    	function createthumb($new_w,$new_h,$x1,$y1,$x2,$y2,$fn)
    	{
    	$src_img=imagecreatefromjpeg($_GET['fn']);
    	$dst_img=ImageCreateTrueColor($new_w,$new_h);
    	imagecopyresampled($dst_img,$src_img,0,0,$x1,$y1,$new_w,$new_h,$x2-$x1,$y2-$y1); 
    
    //output to browser
    	imagejpeg($dst_img);
    //output to file
    	imagejpeg($dst_img,substr($_GET['fn'],0,-4)."_th.jpg"); 
    
    	imagedestroy($dst_img); 
    	imagedestroy($src_img); 
    	}
    	if ($_GET[action]=="generate")
    	{
    	header('Content-type:image/jpeg');
    	createthumb($_GET['w'],$_GET['h'],$_GET['x1'],$_GET['y1'],$_GET['x2'],$_GET['y2'],$_GET['fn']);
    	}
    ?>
    
    //working area
    <div id="image" style="cursor: crosshair; width:<?= $imgWidth ?>px; 
    height:<?= $imgHeight ?>px; border-width:0; background-image: url('<?= $_GET[filename] ?>') ">
    	<div id="area"></div>
    </div>
    
    //input-output form
    <form action="" method="post">
    <table width="<?=$imgWidth?>px">
    	<tr>
    	<td width="33%" align=center>
    	TL (x1, y1) = (<input type="text" id="x1_inp" value="0" class="atc1" onChange="inputXYUpdate();">,
    	<input type="text" id="y1_inp" value="0" class="atc1" onChange="inputXYUpdate();">)<br>
    	BR (x2, y2) = (<input type="text" id="x2_inp" value="0" class="atc1" onChange="inputXYUpdate();">,
    	<input type="text" id="y2_inp" value="0" class="atc1" onChange="inputXYUpdate();">)<br></td>
    	<td width="33%" align=center>
    	Width = 
    	<input type="text" id="th_width" value="0" class="atc2" onChange="inputWidthUpdate();"><br>
    	Height = 
    	<input type="text" id="th_height" value="0" class="atc2" onChange="inputHeightUpdate();"><br></td>
    	<td width="33%" align=center>
    	Thumbnail width = <input type="text" id="th_w" value="" class="atc2"><br>
    	Thumbnail height = <input type="text" id="th_h" value="" class="atc2"><br></td></tr>
    	<tr><td colspan=3 align=center><BR><a href="/none.gif" class="preview"></a></td></tr>
    </table><input type="hidden" value="<?= $fileInput ?>" id="fileName"></form>

    8 Пример работы скрипта

    9 Ссылки

    1. Image previews with DOM JavaScript - icant.co.uk/articles/imagepreview
    2. Сложное масштабирование изображений в PHP - codenet.ru/webmast/php/Image-Resize-GD

    10 Исходный код

    Advanced Thumbnail Creator: atc.zip
    Библиотека thumbcreate.js: thumbcreate.js
    Модуль thumbcreate.php: thumbcreate.php
    Описание в формате PDF: atc.pdf



    Опубликовал admin
    7 Мар, Среда 2007г.



    Программирование для чайников.