Последние записи
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
- Вывод на печать графического файла
- Взаимодействие через командную строку
- Перенести программу из Delphi в Lazarus
- Определить текущую ОС
- Автоматическая смена языка (раскладки клавиатуры)
- Сравнение языков на массивах. Часть 2
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
7th
Сен
Как сделать чтобы делая клик по одному из секторов окружности он выделялся определённым цветом?
Всем доброго времени суток! помогите плиз,есть рисунок две окружности одна в одной и каждая из окружностей разбита на сектора,как сделать чтобы делая клик по одному из секторов он выделялся определённым цветом? (читать всё…)
24th
Авг
Как заполненить форму фоновым рисунком?
Как размножить картинку на форме, для создания бэкграунда? (читать всё…)
18th
Июн
Графика. Вывод узора на экран
Написать программу, которая выводит на экран приведенный ниже узор, можно через рекурсию
(читать всё…)
3rd
Июн
Как сделать плавный переход между картинками?
Здравствуйте, у меня на форме есть кнопки, при щелчке на которые в image должна грузиться определенная картинка. Как можно добиться плавного перехода между последующими картинками? (читать всё…)
17th
Фев
Как сделать большое изображение на маленькой форме?
Столкнулся с такой проблемой….
Имеются много (10к+) картинок 256х256 формата jpg. Необходимо их всех склеить и разместить на форме. При их склеивании образуется оч. большая картинка. Как сделать так, что бы размеры формы остались к примеру 800х800, а картинка была на этой форме в натуральную величину (т.е. не уменьшалась), а передвижение по этой картинке осуществлялось с помощью мышки ( при удержании ЛКМ можно было передвигаться по этой большой картинке ). (читать всё…)
11th
Окт
Рисование многоугольника мышкой
Доброго дня!
Вот всё пытаюсь сделать рисование многоугольника мышкой. Моя логика такая:
static int n=0;
POINT pt[10];
1. Нажатием левой клавиши запоминаю первую точку
case WM_LBUTTONDOWN:
x=LOWORD(lParam); //coordinates 1
y=HIWORD(lParam);
break;
2. Отжатием – запоминаю вторую и последующие
case WM_LBUTTONUP:
hdc=GetDC(hWnd);
x2=LOWORD(lParam); //coordinates 2
y2=HIWORD(lParam);
SelectObject(hdc, hPen);
SelectObject(hdc1, hPen);
if (n==0) {pt[0].x=x; pt[0].y=y;}
n++;
pt[n].x=x2;
pt[n].y=y2;
ReleaseDC (hWnd,hdc);
break;
3. Нажатием правой клавиши рисую получившуюся фигуру:
case WM_RBUTTONDOWN:
hdc=GetDC(hWnd);
SelectObject(hdc, hPen);
SelectObject(hdc1, hPen);
Polygon(hdc,pt,n);
Polygon(hdc1,pt,n);
n=0;
ReleaseDC (hWnd,hdc);
break;
Но не работает. Что я делаю не так?
ТС сам нашел решение:
case WM_LBUTTONDOWN:
x=LOWORD(lParam); //coordinates 1
y=HIWORD(lParam);
if (n==0) {
x0=x;
y0=y;
}
break;
case WM_LBUTTONUP:
hdc=GetDC(hWnd);
x2=LOWORD(lParam); //coordinates 2
y2=HIWORD(lParam);
SelectObject(hdc, hPen);
SelectObject(hdc1, hPen);
//choise++;
//if (choise==6) {choise=1;}
choise=5;
switch (choise) {
case 1:
Rectangle (hdc,x,y, x2,y2);
Rectangle (hdc1,x,y, x2,y2);
break;
case 2:
Ellipse (hdc,x,y, x2,y2);
Ellipse (hdc1,x,y, x2,y2);
break;
case 3:
MoveToEx(hdc,x,y,0);
LineTo (hdc,x2,y2);
MoveToEx(hdc1,x,y,0);
LineTo (hdc1,x2,y2);
break;
case 4:
case 5:
if (n==0)
{
pt[0].x=x;
pt[0].y=y;
pt[1].x=x2;
pt[1].y=y2;
n=1;
MoveToEx(hdc,x,y,0);
LineTo (hdc,x2,y2);
MoveToEx(hdc1,x,y,0);
LineTo (hdc1,x2,y2);
}
else
{
MoveToEx(hdc,x0,y0,0);
LineTo (hdc,x2,y2);
MoveToEx(hdc1,x0,y0,0);
LineTo (hdc1,x2,y2);
pt[n].x=x2;
pt[n].y=y2;
}
n++;
x0=x2; y0=y2; //захоўваем пачатак наступнага адрэзка
break;
}
ReleaseDC (hWnd,hdc);
break;
case WM_RBUTTONDOWN:
hdc=GetDC(hWnd);
SelectObject(hdc, hPen2);
SelectObject(hdc1, hPen2);
if (choise==4) {
Polygon(hdc,pt,n);
Polygon(hdc1,pt,n);
}
if (choise==5) {
Polyline(hdc,pt,n);
Polyline(hdc1,pt,n);
}
ReleaseDC (hWnd,hdc);
break;
25th
Авг
Делаем динамические тени на OPENGL. Часть 1
Здравствуйте. В этой статье я хочу рассмотреть создание движка динамического освещения с помощью графической библиотеки OpenGL. Писаться движок будет на Delphi, но это не мешает переписать его на любой другой язык, так как главное, рассматриваемое в статье, это алгоритмы…
Вадим Буренков
vadim_burenkov@mail.ru
Чтобы не тратить время на инициализацию OpenGL и избежать других проблем (например, с настройкой таймеров и рендера в текстуру) я буду использовать движок ZenGL [1]. Впрочем, от него нам многого не понадобится. Итак, приступим…
Инициализация OpenGL в ZenGL
Первым делом качаем ZenGL и создаем в нем простейшее приложение (вы можете найти его в папке LightEngine ресурсов статьи, там же вы найдете ZenGL):
код:
uses
zgl_main,
zgl_screen,
zgl_window,
zgl_timers,
zgl_textures,
zgl_textures_jpg,
zgl_sprite_2d,
zgl_mouse,
zgl_keyboard,
zgl_utils;
var
BackTex:zglPTexture; // текстура фона
bTiles:zglTTiles2D; // параметры тайлинга
procedure Init;
var n,j:integer;
begin
// отключаем очищение буфера
zgl_disable(COLOR_BUFFER_CLEAR );
// Тут можно выполнять загрузку основных ресурсов
// загрузка текстуры и настройка тайлинга
BackTex:=tex_LoadFromFile( ‘Back.jpg’,0,TEX_DEFAULT_2D);
// параметры тайлов фона
bTiles.Count.X:=7;
bTiles.Count.Y:=5;
bTiles.Size.W:=128;
bTiles.Size.H:=128;
SetLength(bTiles.Tiles,7,5);
&nfor fto=0 to 4 do
&nbsforbsp;&ntob>for j:=0 to 6 do bTiles.Tiles[j,n]:=1;
end;
procedure Draw;
begin
// Тут «рисуем» что угодно 🙂
tiles2d_Draw(BackTex,0,0,BTiles); // отрисовка фона
end;
procedure Update;
begin
// Тут выполняется обработка данных
if key_Press( K_ESCAPE ) then zgl_Exit;
// обновление клавиш
key_ClearState;
Mouse_ClearState;
end;
procedure Timer;
begin
// Будем в заголовке показывать количество кадров в секунду
wnd_SetCaption( ‘LightEngine [ FPS: ‘ + u_IntToStr( zgl_Get(
SYS_FPS ) ) + ‘ ]’ );
end;
procedure Quit;
begin
// Тут выполняется очищение данных
end;
Begin
// Создаем таймер с интервалом 1000мс.
timer_Add( @Timer, 1000 );
// Создаем таймер с интервалом 10мс.
timer_Add( @Update, 10 );
// Регистрируем процедуру, что выполнится сразу после
// инициализации ZenGL
zgl_Reg( SYS_LOAD, @Init );
// Регистрируем процедуру, где будет происходить рендер
zgl_Reg( SYS_DRAW, @Draw );
// Регистрируем процедуру, которая выполнится после завершения
// работы ZenGL
zgl_Reg( SYS_EXIT, @Quit );
// Устанавливаем заголовок окна
// Разрешаем курсор мыши
wnd_ShowCursor( TRUE );
// Указываем первоначальные настройки
scr_SetOptions( 800, 600, REFRESH_MAXIMUM, FALSE, FALSE );
// Инициализируем ZenGL
zgl_Init;
End.
При инициализации мы указываем процедуры в которых будут производится различные действия (инициализация/обработка/очищение) а также параметры окна.
В инициализации загружается текстура и настраивается тайлинг (количество и размер настроен так, чтобы текстура закрывала весь экран). В обработке обновляются состояния мыши и клавиатуры, а также стоит проверка на нажатие ESC. Процедура очищения пока пуста, так как ресурсы движка очищаются самостоятельно.
Другие непонятные процедуры можно посмотреть в справке, которая находится в папке doc движка. Чтобы при компиляции не возникло проблем необходимо указать расположение модулей движка в Project->Options- >Directories/Conditionals->SearchPath, а именно папки zengl/src и zengl/src/PasZLib (см. рис.1). Можно скомпилировать проект, увидеть вы должны следующее (см. рис.2).
Рис. 1. Пути
Рис. 2. Тайлинг
Немного теории
Теперь перейдем к теории вопроса. В движке мы должны реализовать два типа – источники света и объекты, которые отбрасывают тени (см. рис.3):
Рис. 3. Тень от объекта
Источник света обладает параметрами:
- положение
- радиус
- цвет
- интенсивность
Все объекты являются невыпуклыми многоугольниками. Они имеют:
- локальные координаты вершин
- мировые координаты вершин
- количество вершин
- положение
- угол поворота
Локальные координаты нужны, так как через положение и угол поворота объекта его можно разворачивать.
Для хранения данных об освещенности нам понадобятся два буфера размером в экран. Первый – альфа буфер. В него выводится круглый источник света (см. рис.4):
Рис. 4. Источник света
После этого альфа буфер рисуется во второй буфер – буфер аккумуляции. При этом используется аддитивный режим блендинга, то есть цвета смешиваются. В буфере мы получаем такую картинку (см. рис.5):
Рис. 5. Смешивание источников света
В нем светлые участки – там где свет, а темные – там где тьма. А теперь мы выводим буфер аккамуляции на экран с блендингом MULT. Получается так, что чем светлее цвет, тем он прозрачнее (см. рис.6):
Рис. 6. Рисование с блендингом MULT
Как же делаются тени от объектов? При выводе источника света в альфа буфер на него рисуется форма тени черным цветом. Получается что от круга света «отрезают» кусок (см. рис.7):
Рис. 7. Форма тени на свете
С помощью такого алгоритма получаются тени любой сложности, причем их количество, как и источников света с объектами неограниченно (см.рис.8).
Да будет свет!
Под следующий код сделаем модуль, который и будет отвечать за тени. Назовем его ZGLShadows.
Рис. 8. Сцена с большим количеством теней
Напишем тип света:
код:
PLightSource=^TLightSource;
TLightSource=record
position:leVect; // положение
radius:single; // радиус
color:TColorRGB; // цвет
intensivity:single; // интенсивность cвета
prev,next:PLightSource;
end;
Все данные будут храниться в “prev-next” (двухсвязных) списках (см. рис.9):
Рис. 9. Списки
Каждый элемент является звеном цепи и имеет указатели на предыдущее и следующее звено. Нам же нужно иметь первый элемент и длину цепи для управления списком:
код:
// Источники света
le_Lights:PLightSource; // список
le_NumLights:integer; // количество
Более подробно о такой системе хранения данных можно почитать в Интернете. Как мы видим, у нас появились новые типы данных:
код:
TColorRGB=record
r,g,b:single;
end;
Данный тип нужен для хранения цвета в формате rgb, так как его использует OpenGL. ZenGL использует integer для хранения цветов (например $FFFFFF соответствует 1,1,1 в RGB), поэтому нам может понадобится процедура для перевода цвета в RGB:
код:
begin
Result.r := ((Color and $FF0000) shr 16) / 255;
Result.g := ((Color and $FF00) shr 8) / 255;
Result.b := (Color and $FF) / 255;
end;
Все координаты будут храниться в типе:
код:
leVect=record
x,y:single;
end;
Подробнее о нем будет написано позже, пока нам понадобится только формирование вектора по x и y:
код:
begin
result.x:=x;
result.y:=y;
end;
Перейдем к процедурам управления источниками света:
код:
color:TColorRGB):PLightSource;
var t: PLightSource;
begin
new(t);
t.Next:= nil;
t.Prev:= nil;
t.position:=p;
t.radius:=radius;
t.intensivity:=intensivity;
t.color:=color;
t.Next:= le_Lights;
if le_Lights <> nil then le_Lights.Prev:= t;
le_Lights:= t;
Result:= le_Lights;
inc(le_NumLights);
end;
Функция создает источник света в памяти и возвращает указатель на него. Большую часть кода занимает работа со списками.
В следующей процедуре происходит рисование круга света как на рисунке 4. Он рисуется через GL_TRIANGLE_FAN. Первая точка в центре имеет цвет и интенсивность света, далее идут точки по радиусу окружности с нулевым цветом, благодаря чему мы имеем плавный переход цвета:
код:
var angle:single;
begin
angle:=0;
glBegin(GL_TRIANGLE_FAN);
glColor4f(t.color.r, t.color.g, t.color.b, t.intensivity);
glVertex2f(t.position.x,t.position.y);
glColor4f(0, 0, 0, 0 );
while angle<=Pi*2 do begin
glVertex2f( t.radius*cos(angle) + t.position.x,
t.radius*sin(angle) + t.position.y);
angle:=angle+((PI*2)/le_numSubdivisions);
end;
glVertex2f(t.position.x+t.radius, t.position.y);
glEnd();
end;
Количество треугольников, из которого рисуется круг, задается константой:
код:
le_numSubdivisions = 32;
Следующая процедура рассчитывает и рисует тень для объектов, но о ней я напишу позже:
код:
Далее напишем процедуру, которая освобождает память, занятую источником света:
код:
var DelT: PLightSource;
begin
DelT:= t;
if t.Prev <> nil then t.Prev.Next := t.Next
else le_Lights:= t.Next;
if t.Next <> nil then t.Next.Prev := t.Prev;
Dispose(DelT);
dec(le_NumLights);
t:=nil
end;
Следующая процедура вспомогательная, она обрабатывает каждый источник света передаваемой в нее процедурой:
код:
var t, tNext: PLightSource;
begin
t:= le_Lights;
while t <> nil do
begin
tNext:= t.Next;
p(t);
t:= tNext;
end;
end;
le_proc – тип процедуры:
код:
le_proc=procedure(d:Pointer);
Например, данная строчка нарисует все источники света:
код:
Хочу заметить, что при попытке передать в le_EachLightSource процедуру очищения возникнет ошибка, связанная с памятью, поэтому для очищения всех источников света напишем отдельную процедуру:
код:
var t, tNext: PLightSource;
begin
t:= le_Lights;
while t <> nil do begin
tNext:= t.Next;
le_FreeLightSource(t);
t:= tNext;
end;
end;
Заставим это работать
С типом света мы управились, теперь надо заставить его работать. Объявим следующие переменные:
код:
le_AlphaBuffer: zglPRenderTarget; // буфер для света
le_AccBuffer: zglPRenderTarget; // буфер для сложения
// изображений света
le_DarkColor: integer; // цвет тени
В этой процедуре инициализируются буферы для рендеринга. К проекту нужно также подключить модули:
- zgl_textures – создание текстуры-буфера
- zgl_render_target – управление рендерингом
- zgl_primitives_2d – очищение рендер target. Хотя можно было бы просто рисовать QUAD на OpenGL.
- zgl_fx – процедуры управления блендингом
- zgl_sprite_2d – рисование текстур
Напишем процедуру инициализации буферов:
код:
begin
le_DarkColor:=DarkColor;
// инициализация буферов
le_AlphaBuffer:=rtarget_Add( RT_TYPE_FBO, tex_CreateZero(
800,600, 0, TEX_DEFAULT_2D ) , RT_FULL_SCREEN );
le_AccBuffer :=rtarget_Add( RT_TYPE_FBO, tex_CreateZero(
800,600, 0, TEX_DEFAULT_2D ) , RT_FULL_SCREEN );
end;
le_DarkColor – переменная, которая отвечает за освещенность. К ее смыслу и принципу работы я еще вернусь. Обобщающая процедура полной обработки света:
код:
begin
rtarget_Set( le_AlphaBuffer ); // начинаем рендер в буфер
pr2d_Rect(0,0,800,600, 0,255,PR2D_FILL); // очищаем черным
// цветом
le_DrawLightSource(t); // отрисовка источника света
rtarget_Set( nil );
rtarget_Set( le_AccBuffer ); // отрисовка полученного
// изобр-я в буфер аккамуляции
fx_SetBlendMode(FX_BLEND_ADD); // при отрисовке используем
// блендинг для сложения
// интенсивностей источ-в света
ssprite2d_Draw( le_AlphaBuffer.Surface, 0,0,800,600,0);
fx_SetBlendMode(FX_BLEND_NORMAL);
rtarget_Set( nil );
end;
И завершающая процедура – вывод буфера с использованием MULT блендинга:
код:
begin
// выводим полученные тени и свет на экран с использованием
// блендинга mult (чем светлее изображение тем прозрачней)
fx_SetBlendMode(FX_BLEND_MULT);
ssprite2d_Draw( le_AccBuffer.Surface, 0,0,800,600,0);
fx_SetBlendMode(FX_BLEND_NORMAL);
// очищаем буфер для следующего кадра (цветом le_DarkColor!)
rtarget_Set( le_AccBuffer );
pr2d_Rect(0,0,800,600, le_DarkColor,255,PR2D_FILL);
rtarget_Set( nil );
end;
Хочу заметить, что очищение le_AccBuffer проводится цветом le_DarkColor. Следовательно, чем светлее этот цвет тем прозрачнее тени (см. рис.10). На изображении видно, что справа фон просвечивается даже там, где света нет, так как le_DarkColor не черный, а серый ($1f1f1f).
Рис. 10. Различный DarkColor
Все, система света написана. Правда, пока без теней от объектов. Теперь проверим ее в действии.
Добавим переменную под управляемый свет:
код:
UserLight:PLightSource; // указатель на управляемый свет
Создадим его, и еще 4 света в Init:
код:
// загружаем источники света
le_CreateLightSource
(le_v(520,550),400,0.3,IntToRGB($FF00FF));
le_CreateLightSource
(le_v(470,50),250,0.5,IntToRGB($FF0000));
le_CreateLightSource
(le_v(200,300),270,1,IntToRGB($00FF00));
le_CreateLightSource
(le_v(640,270),300,0.8,IntToRGB($FFFFFF));
UserLight:=le_CreateLightSource(le_v(0 ,
0),100,0.8,IntToRGB($FFFFFF));
Теперь в Draw напишем рисование теней:
код:
le_EachLightSource(@le_RenderLight);
// отрисовка теней
le_FinishRender;
В Update привяжем UserLight к мышке, сделаем изменение размера при нажатии на кнопки мыши и цвета при нажатии на колесико:
код:
UserLight.radius:=UserLight.radius+3;
if mouse_Down( M_BRIGHT ) then
if UserLight.radius>0 then
UserLight.radius:=UserLight.radius-3;
if mouse_Click( M_BMIDLE ) then begin
UserLight.color.r:=random(100)/100;
UserLight.color.g:=random(100)/100;
UserLight.color.b:=random(100)/100;
end;
И наконец, в Quit очищаем источники света:
код:
Запускаем, любуемся результатом (см. рис.11).
Рис. 11. Результат
Заключение
В следующей части статьи я рассмотрю создание теней от объектов, а также оптимизирую код, чтобы добиться большей производительности. Весь исходный код проекта приложен к журналу «ПРОграммист. Пятый выпуск».
Продолжение следует…
Ресурсы
- Страница разработчика ZenGL http://andrukun.inf.ua/zengl.html
- Михалкович С.С. Основы программирования.
Второй семестр 08-09, 2 часть
Обсудить на форуме – Делаем динамические тени на OPENGL. Часть 1
21st
Авг
Полупрозрачность в Delphi
И так, как сделать окошко в дельфи прозрачным с красивыми тенями и другой мутью.
Перво наперво, качаем gdiplus.dll (если есть желание) с MS Official Site
Потом смотрим мои (DIB) и не мои (GdiPlus) модули в аттаче.
И так… Подготовим плацдарм для нашего окошка
код:
const
WndClassName = ‘Trulyalya’;
var
WndClass: TWndClass = (
style: CS_DBLCLKS;
cbClsExtra: 0;
cbWndExtra: 0;
hbrBackground: 0;
lpszMenuName: NIL;
lpszClassName: WndClassName;
);
…
initialization
WndClass.lpfnWndProc := @DefWindowProc; // I hope…
WndClass.hInstance := HInstance;
WndClass.hIcon := LoadIcon(HInstance, ‘MAINICON’);
WndClass.hCursor := LoadCursor(0, IDC_ARROW);
Windows.RegisterClass(WndClass);
finalization
Windows.UnregisterClass(WndClassName, HInstance);
И так у нас есть зарегиный класс, вот ведь счастье ну мы не собираемся на этом останавливаться и пойдем до конца! Теперь давайте создадим окошко
Код:
hWnd := CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_LAYERED,
WndClass.lpszClassName, NIL, WS_POPUP or WS_VISIBLE, 0, 0, 0, 0, 0, 0, HInstance, NIL);
Думаю то что здесь, понять не составит труда. Теперь стоит понять, что у нас есть окошко со стилем WS_EX_LAYERED и это дает нам по сути установить и отобразить любое 32х битное изображение разумеется в формате ARGB никакие PNG и т.п. на прямую не ставятся. Как же это сделать?
Код:
Context: GpGraphics;
Tmp: TDIB;
Image: TDIB;
Rect: TRect;
begin
// Rect := GetWindowRect(); / GetClientRect(); не помню как точно, сами разберетесь
Tmp := TDIB.Create(Rect.right – Rect.left, Rect.bottom – Rect.top); // создаем битмап по размеру окна
Image := TDIB.Create(’my_image.png’); // загрузим какое то изображение
GdipCreateFromHDC(Tmp.DC, Context); // создадим контекст GDI+ c Tmp
GdipSetSmoothingMode(Context, SmoothingModeAntiAlias); // antialias включим
GdipSetCompositingMode(Context, CompositingModeSourceCopy); // рисование с перекрытием
GdipSetInterpolationMode(Context, InterpolationModeHighQualityBicubic); // качественно масштабировать изображения
GdipDrawImageRectRect(Context, Image.Bitmap,
0, 0, Tmp.Width, Tmp.Height, // покрываем все окно
0, 0, Image.Width, Image.Height, // берем все изображение
UnitPixel, NIL, NIL, NIL);
GdipDeleteGraphics(Context);
Image.Free();
И так, мы узнали размер окна, создали битпам для окна, загрузили картинку, связали GDI+ с Tmp и нарисовали с помощью GDI+ нашу картинку, потом все освободили. Теперь у нас есть Tmp на с отрисованной картинкой. Осталось дело за малым, отобразить на окне.
Код:
BlendFunc: TBlendFunction;
ZPoint: TPoint;
LeftTop: TPoint;
Size: TSize;
Rect: TRect;
begin
with BlendFunc do
begin
BlendOp := AC_SRC_OVER;
BlendFlags := 0;
AlphaFormat := AC_SRC_ALPHA;
SourceConstantAlpha := 255; // не желательно менять это, да станет прозрачней, но тормаза начнутся, лучше перерисовать сам битмап в более прозрачный.
end;
// Rect := GetWindowRect(); / GetClientRect(); не помню как точно, сами разберетесь
ZPoint := Point(0, 0);
LeftTop := Point(Rect.left, Rect.top);
Size.cx := Rect.right – Rect.left;
Size.cy := Rect.bottom – Rect.top;
UpdateLayeredWindow(hWnd, 0, @LeftTop, @Size, Tmp.DC, @ZPoint, 0, @BlendFunc, ULW_ALPHA);
Разумеется, не забудьте сделать это Tmp.Free();
Опять такие, это мануалчик, проверять не могу сейчас, да и думаю тут суть ясна, садитесь и пробуйте.
DIB.rar
8th
Авг
Как yменьшить картинку с помощью php
// — Настройки
define(’WIDTH’,200); // Ширина иконки
define(’HEIGHT’,200); // Высота иконки
define(’R’,255);define(’G’,255);define(’B’,255); // RGB для фонового цвета под иконкой
// — Поехали
$imageInfo = getimagesize( $file );
switch( $imageInfo[2] ){
case 1: $image = imagecreatefromgif( $file ); break;
case 2: $image = imagecreatefromjpeg( $file ); break;
case 3: $image = imagecreatefrompng( $file ); break;
default: exit();
}
//— Создание иконки фотки
$result = imagecreatetruecolor(WIDTH,HEIGHT);
$bg = imagecolorallocate( $result, R, G, B );
imagefilledrectangle( $result, 0, 0, WIDTH-1, HEIGHT-1, $bg );
//— Вычисляем соотношение сторон для иконки
$ratio1 = $imageInfo[0]/WIDTH;
$ratio2 = $imageInfo[1]/HEIGHT;
$ratio = $ratio1<$ratio2?$ratio1:$ratio2; // выбираем наименьшее соотношение
// if ( $ratio<1 ) $ratio=1; // Оставить иконки меньших размеров WIDTH и HEIGHT не трогать
$width = $imageInfo[0]/$ratio;
$height = $imageInfo[1]/$ratio;
imagecopyresampled( $result, $image, 0, 0, ($imageInfo[0]-WIDTH*$ratio)/2, ($imageInfo[1]-HEIGHT*$ratio)/2, WIDTH, HEIGHT, $ratio*WIDTH, $ratio*HEIGHT);
//— Отправляем (возвращаем) иконку
header(’Content-type: image/jpeg’);
imagejpeg($result);
Алгоритм используется для подготовки эскизов (иконок) изображений.
Причем данная версия для того хороша, когда все фотки каких-попало форматов. И все аккуратненько подгоняются под размер WIDTHхHEIGHT. То, что не влазит, обрезается.
Если обрезание (обрезание исходной картинки имеется ввиду) не нужно, т.е. чтобы эскиз со своими “какими-попало” пропорциями просто вписался в прямоугольник WIDTHхHEIGHT.
Достаточно заменить одну строчку:
…..
imagecopyresampled( $result, $image, 0, 0, ($imageInfo[0]-WIDTH*$ratio)/2, ($imageInfo[1]-HEIGHT*$ratio)/2, WIDTH, HEIGHT, $ratio*WIDTH, $ratio*HEIGHT);
…..
// вот на эту:
imagecopyresampled( $result, $image, (WIDTH-$width)/2, (HEIGHT-$height)/2, 0, 0, $width, $height, $imageInfo[0], $imageInfo[1]);
Облако меток
css реестр ассемблер timer SaveToFile ShellExecute программы массив советы word MySQL SQL ListView pos random компоненты дата LoadFromFile form база данных сеть html php RichEdit indy строки Win Api tstringlist Image мысли макросы Edit ListBox office C/C++ memo графика StringGrid canvas поиск файл Pascal форма Файлы интернет Microsoft Office Excel excel winapi журнал ПРОграммист DelphiКупить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)