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

Рисунок 1 - Исходное изображение
Рисунок 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 Входные и выходные параметры
Входные параметры:
- $_GET[filename] - строка, определяющая имя файла и путь к нему относительно корневого каталога на сервере. Переменная $_GET[filename] должна быть предварительно закодирована функцией urlencode();
- $_GET[thumbwidth] - предустановленная ширина превью изображения. Если этот параметр равен "0" или не определен, ширина превью определяется в зависимости от выбранной области.
- $_GET[thumbheight] - предустановленная высота превью изображения. Если этот параметр равен "0" или не определен, высота превью определяется в зависимости от выбранной области.
Выходные параметры:
- Превью изображения на странице браузера.
- Файл-превью типа JPEG, находящийся в том же каталоге что и исходное изображение.
7 Реализация
Разработанный программный комплекс состоит из двух файлов.
- thumbcreate.js - набор функций для работы с выделяемой областью и функции подготовки генерации изображения.
- 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 Ссылки
- Image previews with DOM JavaScript - http://icant.co.uk/articles/imagepreview/
- Сложное масштабирование изображений в PHP - http://www.codenet.ru/webmast/php/Image-Resize-GD/
9 Исходный код
Advanced Thumbnail Creator: atc.zip
Библиотека thumbcreate.js: thumbcreate.js
Модуль thumbcreate.php: thumbcreate.php
Описание в формате PDF: atc.pdf
© Жупаненко Андрей
research@zhupanenko.com
http://research.zhupanenko.com/atc/
февраль, 2007
|