На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! правила раздела Алгоритмы
1. Помните, что название темы должно хоть как-то отражать ее содержимое (не создавайте темы с заголовком ПОМОГИТЕ, HELP и т.д.). Злоупотребление заглавными буквами в заголовках тем ЗАПРЕЩЕНО.
2. При создании темы постарайтесь, как можно более точно описать проблему, а не ограничиваться общими понятиями и определениями.
3. Приводимые фрагменты исходного кода старайтесь выделять тегами code.../code
4. Помните, чем подробнее Вы опишете свою проблему, тем быстрее получите вразумительный совет
5. Запрещено поднимать неактуальные темы (ПРИМЕР: запрещено отвечать на вопрос из серии "срочно надо", заданный в 2003 году)
6. И не забывайте о кнопочках TRANSLIT и РУССКАЯ КЛАВИАТУРА, если не можете писать в русской раскладке :)
Модераторы: Akina, shadeofgray
  
> Поместить рисунок в холст - оптимально по критерию наибольших видимых габаритов.
    Математическая задачка. Есть холст, который может быть произвольного размера и формы -

    - но фиксированного в конкретный момент времени. Холст - место для рисунка на сайте.

    И есть рисунок. Его размеры и пропорции такие же рэндомные, как у холста, - но когда известны постоянные размеры холста - так же известны и постоянные размеры рисунка.

    При этом, существует явление интерполяции: при рисунке 200x200 и холсте 2000x2000 - рисунок растянет на странице сайта и он займет весь холст - хорошо. И, наоборот, при рисунке 2000x2000 и холсте 200x200 - рисунок тупо сожмет в 100 раз - тоже хорошо.

    Как написать алгоритм, при котором любой рисунок будет помещаться в любой холст - оптимально по критерию наибольшего видимого размера?

    Единственное, что приходит в голову, формулы с пропорциями размеров по ширине и высоте:
    if (dProportion_XY_Picture >= dProportion_XY_Canvas) qsResult += " width=" + qsCanvas_X_Max; //Прилепить к верхней стенке холста.
    else qsResult += " height=" + qsCanvas_Y_Max; //К боковой стенке.

    При этом неуказанная грань размера изображения будет отмасштабирована автоматически.
    Сообщение отредактировано: Сергей85 -
      Чтобы поместить картину в холст по ширине, надо её ширину умножить на dx = ширина_холста / ширина_картины. Можно брать dx меньше (очевидно, в этом случае всё равно поместится по ширине), но нельзя брать больше.
      Всё то же самое справедливо для высоты картины.
      ТО у тебя есть dx и dy, при этом ты можешь их уменьшать, но не можешь увеличивать. Значит итоговый масштабный коэффициент - минимум из этих двух величин, назовём его d.
      А зная масштаб, легко и позицию вычислить, достаточно просто совместить центр картины и центр холста. Т.е. позиция картины в холсте будет
       ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота)/2 )
      .
        Цитата OpenGL @

        Пусть так.

        Но является ли мой представленный способ - рабочим? Ведь не требуется размещать изображение в центре холста, можно и по боку: динамическая сторона автоматически уменьшится, и пустота холста с противоположного бока будет аннулирована.
          Цитата Сергей85 @
          Холст - место для рисунка на сайте.

          Сергей85, по сколько речь идет о сайте ... Но при этом, не идет речь об обработке изображения, кроме как масштабирования - лучше воспользоваться уже готовыми инструментами самих браузеров. Иными словами - за тебя это уже давно решили, просто необходимо правильно применить спецификацию CSS. Для твоего случая на 100% подойдет следующее:

          ExpandedWrap disabled
            object-fit: contain;

          Цитата
          contain
          Смещаемый контент меняет свой размер таким образом, чтобы подстроиться под область внутри блока пропорционально собственным параметрам: окончательный размер контента будет определён как "помещённый внутрь" блока, ограничиваясь его шириной и высотой. Касаемо изображений-фонов, очень похоже на "background-size: contain" - масштабирует картинку так, чтобы она максимально накрыла собой весь блок. Картинка при этом не обрезается, а вписывается в блок с сохранением пропорций. Ссылка на доку

          Вот тебе демонстрационный пример. В нем ты увидишь два варианта:

          • В "холст" размером 200x100 пикселей вписывается изображение размером 120x120 пикселей
          • В "холст" размером 100x200 пикселей вписывается изображение размером 100x300 пикселей

          Как видишь, изображение пытается занять максимальные размеры для отображения, при этом сохраняя свои пропорции. За возможность масштабирования и выравнивания отвечают атрибуты "холстов" - "flex" и "justify-content". При таком использовании отрисовки изображений на веб-странице - вообще не нужно заранее знать/задавать размеры как холстов, так и изображений. Браузер все сделает сам. Однако, при выводе желательно хоть как-то близко подбирать пропорции холста и изображения - тогда "вписывание" будет наиболее удачным.

          И второй момент. Если не устраивают заранее заданные таблицы стилей в отдельном css-файле, то можно использовать атрибут "style" при выводе самой страницы. Разница минимальна (только порядок применения стилей), ну и несколько разрастется сам код страницы.
            Цитата Сергей85 @
            оптимально по критерию наибольшего видимого размера?

            Критерий оптимальности - в студию.

            Если он простой - максимальное масштабирование, при котором ещё нет обрезки, то задача тривиальна. Считаем коэффициенты масштабирования, при которых изображение точно вписывается во фрейм, отдельно по горизонтали и по вертикали, и берём минимальное из них. О чём собственно и сказал OpenGL. Ну и после масштабирования либо центрируем, либо прижимаем вверх-влево - это уже по вкусу.
              Цитата Сергей85 @
              Ведь не требуется размещать изображение в центре холста, можно и по боку: динамическая сторона автоматически уменьшится, и пустота холста с противоположного бока будет аннулирована.

              А это уже не так важно. Просто мне нравится по центру помещать в этом случае :) Но можешь и в (0, 0) поместить, никаких проблем, картинка всё равно поместится в твой холст.
                Цитата Akina @
                Цитата Сергей85 @
                оптимально по критерию наибольшего видимого размера?

                Критерий оптимальности - в студию.

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

                Критерий оптимальности, если перефразировать, - максимально возможные ширина и длина итогового изображения в пикселях.
                  Цитата Сергей85 @
                  Критерий оптимальности, если перефразировать, - максимально возможные ширина и длина итогового изображения в пикселях.

                  А ты не подумал, что такая формулировка НЕ ТРЕБУЕТ сохранения пропорций?
                    Цитата Akina @
                    А ты не подумал, что такая формулировка НЕ ТРЕБУЕТ сохранения пропорций?

                    Уверен, это он просто забыл упомянуть :)
                      Цитата OpenGL @
                      Чтобы поместить картину в холст по ширине, надо её ширину умножить на dx = ширина_холста / ширина_картины. Можно брать dx меньше (очевидно, в этом случае всё равно поместится по ширине), но нельзя брать больше.
                      Всё то же самое справедливо для высоты картины.
                      ТО у тебя есть dx и dy, при этом ты можешь их уменьшать, но не можешь увеличивать. Значит итоговый масштабный коэффициент - минимум из этих двух величин, назовём его d.
                      А зная масштаб, легко и позицию вычислить, достаточно просто совместить центр картины и центр холста. Т.е. позиция картины в холсте будет
                       ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота)/2 )
                      .

                      А не совокупность ли это вариантов, в зависимости от минимальности одной величины от другой?

                      ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота)/2 )

                      ИЛИ

                      ( (холст.ширина - картина.ширина)/2, (холст.высота - картина.высота*d)/2 )

                      Добавлено
                      Да, действительно, отрицательные значения. Используйте холст 100x100 и изображение 10000x10000. В иксе будет 0, в игреке будет -9900/2.
                      Сообщение отредактировано: Сергей85 -
                        Цитата Сергей85 @
                        А не совокупность ли это вариантов, в зависимости от минимальности одной величины от другой?

                        Я там d забыл во второй части :) Разумеется, оно в обоих координатах должно быть:
                        ( (холст.ширина - картина.ширина*d)/2, (холст.высота - картина.высота * d)/2 )
                          В общем, получились те же яйца - только в профиль. За эти месяцы ни разу не подвел.

                          ExpandedWrap disabled
                            {
                                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>";
                            }
                          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0388 ]   [ 14 queries used ]   [ Generated: 27.07.24, 03:13 GMT ]