
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.9.175] |
![]() |
|
Сообщ.
#1
,
|
|
|
Математическая задачка. Есть холст, который может быть произвольного размера и формы -
- но фиксированного в конкретный момент времени. Холст - место для рисунка на сайте. И есть рисунок. Его размеры и пропорции такие же рэндомные, как у холста, - но когда известны постоянные размеры холста - так же известны и постоянные размеры рисунка. При этом, существует явление интерполяции: при рисунке 200x200 и холсте 2000x2000 - рисунок растянет на странице сайта и он займет весь холст - хорошо. И, наоборот, при рисунке 2000x2000 и холсте 200x200 - рисунок тупо сожмет в 100 раз - тоже хорошо. Как написать алгоритм, при котором любой рисунок будет помещаться в любой холст - оптимально по критерию наибольшего видимого размера? Единственное, что приходит в голову, формулы с пропорциями размеров по ширине и высоте: if (dProportion_XY_Picture >= dProportion_XY_Canvas) qsResult += " width=" + qsCanvas_X_Max; //Прилепить к верхней стенке холста. else qsResult += " height=" + qsCanvas_Y_Max; //К боковой стенке. При этом неуказанная грань размера изображения будет отмасштабирована автоматически. |
![]() |
Сообщ.
#2
,
|
|
Чтобы поместить картину в холст по ширине, надо её ширину умножить на dx = ширина_холста / ширина_картины. Можно брать dx меньше (очевидно, в этом случае всё равно поместится по ширине), но нельзя брать больше.
Всё то же самое справедливо для высоты картины. ТО у тебя есть dx и dy, при этом ты можешь их уменьшать, но не можешь увеличивать. Значит итоговый масштабный коэффициент - минимум из этих двух величин, назовём его d. А зная масштаб, легко и позицию вычислить, достаточно просто совместить центр картины и центр холста. Т.е. позиция картины в холсте будет ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота)/2 ). |
Сообщ.
#3
,
|
|
|
Цитата OpenGL @ Пусть так. Но является ли мой представленный способ - рабочим? Ведь не требуется размещать изображение в центре холста, можно и по боку: динамическая сторона автоматически уменьшится, и пустота холста с противоположного бока будет аннулирована. |
Сообщ.
#4
,
|
|
|
Цитата Сергей85 @ Холст - место для рисунка на сайте. Сергей85, по сколько речь идет о сайте ... Но при этом, не идет речь об обработке изображения, кроме как масштабирования - лучше воспользоваться уже готовыми инструментами самих браузеров. Иными словами - за тебя это уже давно решили, просто необходимо правильно применить спецификацию CSS. Для твоего случая на 100% подойдет следующее: ![]() ![]() object-fit: contain; Цитата contain Смещаемый контент меняет свой размер таким образом, чтобы подстроиться под область внутри блока пропорционально собственным параметрам: окончательный размер контента будет определён как "помещённый внутрь" блока, ограничиваясь его шириной и высотой. Касаемо изображений-фонов, очень похоже на "background-size: contain" - масштабирует картинку так, чтобы она максимально накрыла собой весь блок. Картинка при этом не обрезается, а вписывается в блок с сохранением пропорций. Ссылка на доку Вот тебе демонстрационный пример. В нем ты увидишь два варианта: Как видишь, изображение пытается занять максимальные размеры для отображения, при этом сохраняя свои пропорции. За возможность масштабирования и выравнивания отвечают атрибуты "холстов" - "flex" и "justify-content". При таком использовании отрисовки изображений на веб-странице - вообще не нужно заранее знать/задавать размеры как холстов, так и изображений. Браузер все сделает сам. Однако, при выводе желательно хоть как-то близко подбирать пропорции холста и изображения - тогда "вписывание" будет наиболее удачным. И второй момент. Если не устраивают заранее заданные таблицы стилей в отдельном css-файле, то можно использовать атрибут "style" при выводе самой страницы. Разница минимальна (только порядок применения стилей), ну и несколько разрастется сам код страницы. |
![]() |
Сообщ.
#5
,
|
|
Цитата Сергей85 @ оптимально по критерию наибольшего видимого размера? Критерий оптимальности - в студию. Если он простой - максимальное масштабирование, при котором ещё нет обрезки, то задача тривиальна. Считаем коэффициенты масштабирования, при которых изображение точно вписывается во фрейм, отдельно по горизонтали и по вертикали, и берём минимальное из них. О чём собственно и сказал OpenGL. Ну и после масштабирования либо центрируем, либо прижимаем вверх-влево - это уже по вкусу. |
![]() |
Сообщ.
#6
,
|
|
Цитата Сергей85 @ Ведь не требуется размещать изображение в центре холста, можно и по боку: динамическая сторона автоматически уменьшится, и пустота холста с противоположного бока будет аннулирована. А это уже не так важно. Просто мне нравится по центру помещать в этом случае ![]() |
Сообщ.
#7
,
|
|
|
Цитата Akina @ Цитата Сергей85 @ оптимально по критерию наибольшего видимого размера? Критерий оптимальности - в студию. Если он простой - максимальное масштабирование, при котором ещё нет обрезки, то задача тривиальна. Считаем коэффициенты масштабирования, при которых изображение точно вписывается во фрейм, отдельно по горизонтали и по вертикали, и берём минимальное из них. О чём собственно и сказал OpenGL. Ну и после масштабирования либо центрируем, либо прижимаем вверх-влево - это уже по вкусу. Критерий оптимальности, если перефразировать, - максимально возможные ширина и длина итогового изображения в пикселях. |
![]() |
Сообщ.
#8
,
|
|
Цитата Сергей85 @ Критерий оптимальности, если перефразировать, - максимально возможные ширина и длина итогового изображения в пикселях. А ты не подумал, что такая формулировка НЕ ТРЕБУЕТ сохранения пропорций? |
Сообщ.
#9
,
|
|
|
Цитата Akina @ А ты не подумал, что такая формулировка НЕ ТРЕБУЕТ сохранения пропорций? Уверен, это он просто забыл упомянуть ![]() |
Сообщ.
#10
,
|
|
|
Цитата OpenGL @ Чтобы поместить картину в холст по ширине, надо её ширину умножить на dx = ширина_холста / ширина_картины. Можно брать dx меньше (очевидно, в этом случае всё равно поместится по ширине), но нельзя брать больше. Всё то же самое справедливо для высоты картины. ТО у тебя есть dx и dy, при этом ты можешь их уменьшать, но не можешь увеличивать. Значит итоговый масштабный коэффициент - минимум из этих двух величин, назовём его d. А зная масштаб, легко и позицию вычислить, достаточно просто совместить центр картины и центр холста. Т.е. позиция картины в холсте будет ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота)/2 ). А не совокупность ли это вариантов, в зависимости от минимальности одной величины от другой? ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота)/2 ) ИЛИ ( (холст.ширина - картина.ширина)/2, (холст.высота - картина.высота*d)/2 ) Добавлено Да, действительно, отрицательные значения. Используйте холст 100x100 и изображение 10000x10000. В иксе будет 0, в игреке будет -9900/2. |
![]() |
Сообщ.
#11
,
|
|
Цитата Сергей85 @ А не совокупность ли это вариантов, в зависимости от минимальности одной величины от другой? Я там d забыл во второй части ![]() ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота * d)/2 ) |
Сообщ.
#12
,
|
|
|
В общем, получились те же яйца - только в профиль. За эти месяцы ни разу не подвел.
![]() ![]() { const int iCanvas_X_Max = 639; //При печати: пикселей в миллиметре - 3.457шт. Соответствует ширине листа A4 210мм, минус края 24мм, минус 4 пикселя (почему они лишние - неясно). //Ранее было 365. 1 пиксель - жертва за ускорение разрыва страниц с помощью тега <DIV>. const int iCanvas_Y_Max = 364; //При печати: чтобы таблица с максимально 30 строками, идущая после рисунка, не уехала на другой лист. Т.о., на каждую зону - свой отдельный лист. //Нужен анализ, как правильно поместить изображение в холст - чтобы его отображение было максимально большим, не растянутым и не обрезанным. const double dProportion_XY_Canvas = 1.0*iCanvas_X_Max/iCanvas_Y_Max; //Пропорция сторон холста. const double dProportion_XY_Picture = 1.0*iPicture_Width/iPicture_Height; //Пропорция сторон изображения. //Для <IMG> нужно указывать и высоту тоже. Иначе при пустом изображении в принтер помещается значок отсутствующего рисунка, размеры которого иные, - высота искажается - текст съезжает - создание разрыва страницы работает неправильно. const double dProportion_XX = 1.0*iCanvas_X_Max/iPicture_Width; const double dProportion_YY = 1.0*iCanvas_Y_Max/iPicture_Height; qsResult += "<br><center><img src=\"" + qsTemp_Dir + "/" + qsZone_Number + "заменить_на_пустоту.png\""; //Чтобы отчет изготавливался быстро: чем больше разрешение - тем больше тормозит сохранение в PDF - и, как следствие, тормозит и функция создания разрыва страниц. if (dProportion_XY_Picture >= dProportion_XY_Canvas) qsResult += " width=" + QString::number(iCanvas_X_Max) + " height=" + QString::number(round(iPicture_Height*dProportion_XX)); else qsResult += " width=" + QString::number(round(iPicture_Width*dProportion_YY)) + " height=" + QString::number(iCanvas_Y_Max); qsResult += "></img></center><br>"; } |