Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/26: Рейтинг темы: голосов - 26, средняя оценка - 4.62
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266

Необычный фильтр для картинок

04.08.2019, 11:56. Показов 5441. Ответов 62
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Решил написать фильтр для картинок в стиле дальтонизма с тремя режимами (Протанопия,Дейтеранопия,Тританопия)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
float p(float chislo,float protsent){
    return chislo*protsent/100.0;
}
 
TColor Protan(TColor old)
{
long double r,g ,b;
r=GetRValue(old);
g=GetGValue(old);
b=GetBValue(old);
long double  r1,g1,b1;
r1=p(r,20)+p(g,99)-p(b,19);
g1=p(r,16)+p(g,79)+p(b,4);
b1=p(r,1)-p(g,1)+p(b,100);
if (r1>255) r1=255;
if (g1>255) g1=255;
if (b1>255) b1=255;
if (r1<0) r1=0;
if (g1<0) g1=0;
if (b1<0) b1=0;
return  (TColor) RGB (r1, g1, b1);
}
 
TColor Deutran(TColor old)
{
long double r,g ,b;
r=GetRValue(old);
g=GetGValue(old);
b=GetBValue(old);
long double  r1,g1,b1;
r1=p(r,43)+p(g,72)-p(b,15);
g1=p(r,34)+p(g,57)+p(b,9);
b1=p(g,3)-p(r,2)+p(b,100);
if (r1>255) r1=255;
if (g1>255) g1=255;
if (b1>255) b1=255;
if (r1<0) r1=0;
if (g1<0) g1=0;
if (b1<0) b1=0;
return  (TColor) RGB (r1, g1, b1);
}
 
TColor Tritan(TColor old)
{
long double r,g ,b;
r=GetRValue(old);
g=GetGValue(old);
b=GetBValue(old);
long double  r1,g1,b1;
r1=p(r,97)+p(g,11)-p(b,8);
g1=p(r,2)+p(g,82)+p(b,16);
b1=p(g,88)-p(r,6)+p(b,18);
if (r1>255) r1=255;
if (g1>255) g1=255;
if (b1>255) b1=255;
if (r1<0) r1=0;
if (g1<0) g1=0;
if (b1<0) b1=0;
return  (TColor) RGB (r1, g1, b1);
}
 
TBitmap* Linear(int typ)
{
TJPEGImage *jpg = new TJPEGImage();
jpg->LoadFromFile(filen);
Graphics::TBitmap *bmp1, *bmp2;
bmp1 = new Graphics::TBitmap();
bmp1->Assign(jpg);
if (typ==0) return bmp1;
if(bmp1->PixelFormat == pf24bit)
{
RGBTRIPLE*ptr;
for(int y = 0; y < bmp1->Height; y++)
{
ptr = (RGBTRIPLE*)bmp1->ScanLine[y];
for (int x = 0; x < bmp1->Width; x++)
{
if (typ==1) bmp1->Canvas->Pixels[x][y]=Protan((TColor)RGB(ptr[x].rgbtRed, ptr[x].rgbtGreen, ptr[x].rgbtBlue));
else if (typ==2)    bmp1->Canvas->Pixels[x][y]=Deutran((TColor)RGB(ptr[x].rgbtRed, ptr[x].rgbtGreen, ptr[x].rgbtBlue));
else if (typ==3)    bmp1->Canvas->Pixels[x][y]=Tritan((TColor)RGB(ptr[x].rgbtRed, ptr[x].rgbtGreen, ptr[x].rgbtBlue));
}
}
}
return bmp1;
}
Но работает медленно. В чем проблема?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.08.2019, 11:56
Ответы с готовыми решениями:

GetOpenFileName - установить фильтр для текстовых файлов и картинок
Добрый вечер. Сделал открытие и показ только txt файлов, еще хочу что бы картинки показывало. Как дополнить? ...

Необычный код - необычный результат.
Бросте на форму PaintBox и сделайте Align alClient. В OnPaint напишите так: procedure TForm1.PaintBox1Paint(Sender: TObject); var ...

Необычный вопрос, но как раскрутить сервис для людей?
Может немного необычный вопрос, но хочется узнать, если ты создал сервис, то как можно донести информацию о нем? Куда можно обращаться, что...

62
 Аватар для FFPowerMan
2156 / 1236 / 508
Регистрация: 11.10.2018
Сообщений: 6,249
04.08.2019, 15:21
Цитата Сообщение от viramir Посмотреть сообщение
C++
1
long double r, g, b;
- зачем заводить long double? Цвет кодируется байтом - тип unsigned char.

Добавлено через 5 минут
Цитата Сообщение от viramir Посмотреть сообщение
C++
1
2
3
if(r1 > 255) r1 = 255;
if(g1 > 255) g1 = 255;
if(b1 > 255) b1=255;
- Видите?
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 15:24  [ТС]
Цитата Сообщение от FFPowerMan Посмотреть сообщение
- зачем заводить long double? Цвет кодируется байтом - тип unsigned char.

Добавлено через 5 минут

- Видите?
Пока я эти ограничители не ввел,все было в пятнах. а как дубл заменил на чар,так снова пятна полезли,даже с ограничителями
0
 Аватар для FFPowerMan
2156 / 1236 / 508
Регистрация: 11.10.2018
Сообщений: 6,249
04.08.2019, 15:28
В Билдере все работы с изображениями осуществляются очень медленно. Вот я делал:
Как убыстрить движение картинки?
Эффект Melt - раcплавление из игры Doom. Он должен делаться 1-2(сек.), как все прекрасно знают, а там он идет где0то минут 8. Подумайте над этим.
Для ускорения испльзуются OpenGL, Direct3D, DirectX и им подобные системы. Они имеют шейдеры - программы, которые работают напрямую в видеопроцессоре и с видеопамятью, иначе Вы знаете, что получится.

Добавлено через 1 минуту
Цитата Сообщение от viramir Посмотреть сообщение
Пока я эти ограничители не ввел,все было в пятнах. а как дубл заменил на чар,так снова пятна полезли,даже с ограничителями
- это не ограничители, цвет кодировать long double - грубейшая ошибка. 1 цвет = 1 байт.
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 15:29  [ТС]
я ограничителями назвал ифы
C++
1
2
3
4
5
6
if (r1>255) r1=255;
if (g1>255) g1=255;
if (b1>255) b1=255;
if (r1<0) r1=0;
if (g1<0) g1=0;
if (b1<0) b1=0;
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 15:36  [ТС]
Цитата Сообщение от FFPowerMan Посмотреть сообщение
В Билдере все работы с изображениями осуществляются очень медленно. Вот я делал:
Как убыстрить движение картинки?
Эффект Melt - раcплавление из игры Doom. Он должен делаться 1-2(сек.), как все прекрасно знают, а там он идет где0то минут 8. Подумайте над этим.
Для ускорения испльзуются OpenGL, Direct3D, DirectX и им подобные системы. Они имеют шейдеры - программы, которые работают напрямую в видеопроцессоре и с видеопамятью, иначе Вы знаете, что получится.

Добавлено через 1 минуту
- это не ограничители, цвет кодировать long double - грубейшая ошибка. 1 цвет = 1 байт.
все равно пятна,когда было double пятен не было
Оригинал

Обработка
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 15:41  [ТС]
Цитата Сообщение от FFPowerMan Посмотреть сообщение
В Билдере все работы с изображениями осуществляются очень медленно. Вот я делал:
Как убыстрить движение картинки?
Эффект Melt - раcплавление из игры Doom. Он должен делаться 1-2(сек.), как все прекрасно знают, а там он идет где0то минут 8. Подумайте над этим.
Для ускорения испльзуются OpenGL, Direct3D, DirectX и им подобные системы. Они имеют шейдеры - программы, которые работают напрямую в видеопроцессоре и с видеопамятью, иначе Вы знаете, что получится.

Добавлено через 1 минуту
- это не ограничители, цвет кодировать long double - грубейшая ошибка. 1 цвет = 1 байт.
В чем причина пятен?
0
 Аватар для FFPowerMan
2156 / 1236 / 508
Регистрация: 11.10.2018
Сообщений: 6,249
04.08.2019, 17:33
Откуда я знаю? Значит картинка так формируется.

Добавлено через 10 минут
Я не знаю отчего пятна, изучите как цвет формируется и нужно изучить тип данных TColor. Я настаиваю, чтобы Вы убрали long double в сторону unsigned char для R, G и B. - Это международная общепринятая система цветов TrueColor: 8 +
8 + 8 цветов RGB.
C++
1
2
3
if(r1 > 255) r1 = 255;
if(g1 > 255) g1 = 255;
if(b1 > 255) b1 = 255;
- это ограничители.
Пятна: из белого в желтый - гасится синий цвет. Вероятно срабатывает условие:
C++
1
if(b1 < 0) b1 = 0;
Нужно смотреть дебаггером/отладчиком каждый пиксель и какие у него цвета.

Добавлено через 26 минут
Там где пятна - там сильно ярко белый, за границу, наверное, улетает и все.
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 17:35  [ТС]
Цитата Сообщение от FFPowerMan Посмотреть сообщение
Откуда я знаю? Значит картинка так формируется.

Добавлено через 10 минут
Я не знаю отчего пятна, изучите как цвет формируется и нужно изучить тип данных TColor. Я настаиваю, чтобы Вы убрали long double в сторону unsigned char для R, G и B. - Это международная общепринятая система цветов TrueColor: 8 +
8 + 8 цветов RGB.
C++
1
2
3
if(r1 > 255) r1 = 255;
if(g1 > 255) g1 = 255;
if(b1 > 255) b1 = 255;
- это ограничители.
Пятна: из белого в желтый - гасится синий цвет. Вероятно срабатывает условие:
C++
1
if(b1 < 0) b1 = 0;
Нужно смотреть дебаггером/отладчиком каждый пиксель и какие у него цвета.

Добавлено через 26 минут
Там где пятна - там сильно ярко белый, за границу, наверное, улетает и все.
Я сделал фильтр на основе файлов микширования каналов в фотошопе и что-то видно напутал


0
 Аватар для FFPowerMan
2156 / 1236 / 508
Регистрация: 11.10.2018
Сообщений: 6,249
04.08.2019, 17:55
А функции GetRValue(), GetGValue() и GetBValue() сами писали?
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 17:57  [ТС]
Цитата Сообщение от FFPowerMan Посмотреть сообщение
А функции GetRValue(), GetGValue() и GetBValue() сами писали?
Нет,они стандартные,я писал только для извлечения процента.
А те функции это WINAPI
0
 Аватар для FFPowerMan
2156 / 1236 / 508
Регистрация: 11.10.2018
Сообщений: 6,249
04.08.2019, 18:04
http://www.realcoding.net/arti... value.html
Функция возвращает байт.
Сможете добавить в программу просмотрщик определенного пикселя, чтобы посмотреть какой цвет в желтых пятнах?
И то, что JPEG используете - может быть от этого какие-нибудь косяки?
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 18:05  [ТС]
Цитата Сообщение от FFPowerMan Посмотреть сообщение
http://www.realcoding.net/arti... value.html
Функция возвращает байт.
Сможете добавить в программу просмотрщик определенного пикселя, чтобы посмотреть какой цвет в желтых пятнах?
И то, что JPEG используете - может быть от этого какие-нибудь косяки?
А есть способ не использовать Get*Value?
0
 Аватар для FFPowerMan
2156 / 1236 / 508
Регистрация: 11.10.2018
Сообщений: 6,249
04.08.2019, 18:10
Это лучшее и наиболее рациональное решение. Я же Вам объяснял про 3 цвета по байту.

Добавлено через 1 минуту
Ну и сами можете написать, только long double я не вижу смысла использовать. - Всегда используется 3 байта - по байту каждого цвета.
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 18:31  [ТС]
Цитата Сообщение от FFPowerMan Посмотреть сообщение
Это лучшее и наиболее рациональное решение. Я же Вам объяснял про 3 цвета по байту.

Добавлено через 1 минуту
Ну и сами можете написать, только long double я не вижу смысла использовать. - Всегда используется 3 байта - по байту каждого цвета.
Потом нашел реализацию похожего фильтра на java и вообще сломал мозг
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//
//  CB_Filter_Linear.java
//  CBSim
//
//  Created by Loren Petrich on 8/7/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//
 
public class CB_Filter_Linear extends CB_Filter
{
    // Transformation matrices:
    public static final double TransformMatrices[][][] =
    {
        {
            {0.202001295331, 0.991720719265, -0.193722014597},
            {0.163800203026, 0.792663865514, 0.0435359314602},
            {0.00913336570448, -0.0132684300993, 1.00413506439}
        },
        {
            {0.430749076295, 0.717402505462, -0.148151581757},
            {0.336582831043, 0.574447762213, 0.0889694067435},
            {-0.0236572929497, 0.0275635332006, 0.996093759749}
        },
        {
            {0.971710712275, 0.112392320487, -0.0841030327623},
            {0.0219508442818, 0.817739672383, 0.160309483335},
            {-0.0628595877201, 0.880724870686, 0.182134717034}
        },
        {
            {0.316086131719, 0.854894118151, -0.170980249869},
            {0.250572926562, 0.683189199376, 0.0662378740621},
            {-0.00735450321111, 0.00718184676374, 1.00017265645}
        }
    };
    
    private double TransformMatrix[][];
    
    public void SetTransformType(int cbtype)
    {
        TransformMatrix = TransformMatrices[cbtype];
    }
    
    public void DoTransform(double[] ClrIn, double[] ClrOut)
    {
        for (int i=0; i<3; i++)
        {
            double[] Row = TransformMatrix[i];
            double sum = 0;
            for (int j=0; j<3; j++)
                sum += Row[j]*ClrIn[j];
            ClrOut[i] = sum;
        }
    }
}
0
2637 / 1648 / 267
Регистрация: 19.02.2010
Сообщений: 4,368
04.08.2019, 20:27
Лучший ответ Сообщение было отмечено viramir как решение

Решение

Цитата Сообщение от viramir Посмотреть сообщение
Но работает медленно. В чем проблема?
При обработке каждого пиксела (любой из трёх дальтонических функций) - получается 9 вызовов функции p().
Заинлайните p(), ну и вынесите общие вычисления (деление на 100) за скобки (дабы вместо 9 делений на пиксел стало 3).

Если билдер старый или прога компилируется под Вин32 - то там конверсия плавучки в целое выполняется с помощью ОЧЕНЬ медленной (тормознее раз в 10 от идеала) библиотечной функции (которую компилятор вызывает невидимо для программиста). Может, стоит перевести все вычисления с плавучки на целые числа, дабы исчезла надобность в последующей конверсии типов.

Ну и bmp1->Canvas можно предварительно сохранить в локальную переменную - дабы использовать её и избавиться от постоянного (на каждом пикселе) вызова get-функции для свойства Canvas.


Глупость про проведение вычислений в unsigned char - не слушайте.
Можете вместо флоата/дабла взять инт - но к unsigned char пусть оно приводится только и именно при выполнении =(TColor) RGB (r1, g1, b1); (вернее, компилятор сам там возьмёт младшие байты от интов, т.е. приводить вручную ничего не надо).
Ибо если первоначально у Вас всё считалось нормально и до обрезки цвета границами 0/255 выходило, например, 260 - то с unsigned char Вы значение 260 (которое потом обрежется до 255) не получите. Вы получите переполнение и значение 5.
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 20:32  [ТС]
Цитата Сообщение от VTsaregorodtsev Посмотреть сообщение
При обработке каждого пиксела (любой из трёх дальтонических функций) - получается 9 вызовов функции p().
Заинлайните p(), ну и вынесите общие вычисления (деление на 100) за скобки (дабы вместо 9 делений на пиксел стало 3).

Если билдер старый или прога компилируется под Вин32 - то там конверсия плавучки в целое выполняется с помощью ОЧЕНЬ медленной (тормознее раз в 10 от идеала) библиотечной функции (которую компилятор вызывает невидимо для программиста). Может, стоит перевести все вычисления с плавучки на целые числа, дабы исчезла надобность в последующей конверсии типов.

Ну и bmp1->Canvas можно предварительно сохранить в локальную переменную - дабы использовать её и избавиться от постоянного (на каждом пикселе) вызова get-функции для свойства Canvas.


Глупость про проведение вычислений в unsigned char - не слушайте.
Можете вместо флоата/дабла взять инт - но к unsigned char пусть оно приводится только и именно при выполнении =(TColor) RGB (r1, g1, b1); (вернее, компилятор сам там возьмёт младшие байты от интов, т.е. приводить вручную ничего не надо).
Ибо если первоначально у Вас всё считалось нормально и до обрезки цвета границами 0/255 выходило, например, 260 - то с unsigned char Вы значение 260 (которое потом обрежется до 255) не получите. Вы получите переполнение и значение 5.
bmp1->Canvas в какой тип сохраняется?
0
2637 / 1648 / 267
Регистрация: 19.02.2010
Сообщений: 4,368
04.08.2019, 20:37
Цитата Сообщение от viramir Посмотреть сообщение
bmp1->Canvas в какой тип сохраняется?
TCanvas *
0
1 / 1 / 1
Регистрация: 04.05.2016
Сообщений: 266
04.08.2019, 21:03  [ТС]
Цитата Сообщение от VTsaregorodtsev Посмотреть сообщение
TCanvas *
Большое вам спасибо Сделал еще функцию Gray. Тоже взял значения с фотошопа

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TColor Gray(TColor old)
{
int  r,g ,b;
r=GetRValue(old);
g=GetGValue(old);
b=GetBValue(old);
int   r1,g1,b1;
r1=p(r,30)+p(g,59)+p(b,11);
g1=p(r,30)+p(g,59)+p(b,11);
b1=p(r,30)+p(g,59)+p(b,11);
if (r1>255) r1=255;
if (g1>255) g1=255;
if (b1>255) b1=255;
if (r1<0) r1=0;
if (g1<0) g1=0;
if (b1<0) b1=0;
return  (TColor) RGB (r1, g1, b1);
}
0
2637 / 1648 / 267
Регистрация: 19.02.2010
Сообщений: 4,368
05.08.2019, 00:42
Лучший ответ Сообщение было отмечено viramir как решение

Решение

Цитата Сообщение от viramir Посмотреть сообщение
Сделал еще функцию Gray.
Я хочу это развидеть!!!
Ибо нет слов - только матерные старый анекдот про ошибку в ДНК.

Короче, не надо делать ОДНИ И ТЕ ЖЕ вычисления три раза - вполне хватит одного:
C++
1
2
3
4
5
6
7
8
9
10
11
TColor Gray(TColor old)
{
    int  r,g ,b;
    r=GetRValue(old);
    g=GetGValue(old);
    b=GetBValue(old);
    int gray=p(r,30)+p(g,59)+p(b,11);
    if (gray>255) gray=255;
    if (gray<0) gray=0;
    return  (TColor) RGB (gray, gray, gray);
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.08.2019, 00:42
Помогаю со студенческими работами здесь

Необычный join (применить условие where для первой таблицы, а потом where для результата join)
мне нужно прежде чем джоинить, применить условие where для первой таблицы. а потом where для результат джойна. как быть? в строение join...

Конфигурация сайта для Magento 2. Cache TTL для картинок
Сайт на Magento 2.3 На сайте имеются картинки продуктов хранящиеся в /public_html/pub/media/catalog/product Также есть самописный...

Программа для вывода картинок (карточки для изучения ин.яз)
Люди добрые, меня зовут Иляна. Извините что я к вам обращаюсь. Дело в том что сейчас я и моя группа изучаем иностранный язык (а именно...

Фильтр для питания для применения в автомобилях
Разработал источник питания на постоянное напряжения для применения в автомобилях Типовое потребление оборудования около 10А. Так...

Фильтр по форме по нескольким логическим полям с использованием кнопки Общий фильтр
Здравствуйте! Есть простая таблица и созданная форма. Идея в том, чтобы ставя галки осуществлять поиск (с помощью кнопки общий фильтр...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
Установка Emscripten SDK (emsdk) и CMake на Windows для сборки C и C++ приложений в WebAssembly (Wasm)
8Observer8 30.01.2026
Чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git. . .
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru