На главную... Продукты | Технологии | Классификаторы | Проекты | Скачать | Цены| Форум | Статьи | Обучение | Контакты

Копирование подложки в XIMAGEDESC и последующая прорисовка на ней пользовательских сайтов

Поиск  Пользователи  Правила  Войти
Форум » Linux » Средства разработки ГИС-приложений для Linux
Страницы: 1
RSS
Копирование подложки в XIMAGEDESC и последующая прорисовка на ней пользовательских сайтов
 
Здравствуйте! Нужна ваша помощь.
Требуется скопировать в XIMAGEDESC попиксельно подложку, после чего нарисовать поверх нее отдельно
открытые sit-файлы с пользовательскими объектами. Вот код который это делает:
Код
const QImage bufferImage = ...; //буффер с фоновым изображением

DFRAME frame; //прямоугольник для отрисовки (в плоско-прямоугольных координатах)
... задание габаритов frame

XIMAGEDESC ximagedesc; //структура для формирования суммарного изображения (размер как у bufferImage)
... задание параметров ximagedesc

HPAINT hPaint = mapCreatePaintControl(hMap);

//по логике не нужный, но по факту требуемый блок кода от которого хочется избавиться 
HSELECT hSelect = mapCreateMapSelectContext(hMap);
mapSelectLayer(hSelect, -1, 0);
mapPaintByFrameToXImagePro(hMap, const_cast<XIMAGEDESC *>(&ximagedesc), -2,
                           const_cast<DFRAME *>(&frame), ximagedesc.Width, ximagedesc.Height, 0, hSelect, hPaint);

//копирование пикселей подложки
memcpy(ximagedesc.Point, bufferImage.constBits(), bufferImage.byteCount());

//прорисовка отдельно открытых сайтов 
drawSite(site1, ximagedesc, frame, hPaint);
drawSite(site2, ximagedesc, frame, hPaint);

mapFreePaintControl(hPaint);


void drawSite(HMAP hSiteMap, const XIMAGEDESC &ximagedesc, const DFRAME &frame, HPAINT hPaint)
{
    mapPaintByFrameToXImagePro(hSiteMap, const_cast<XIMAGEDESC *>(&ximagedesc), -2, const_cast<DFRAME *>(&frame),
                               ximagedesc.Width, ximagedesc.Height, 0, 0, hPaint);
}

Что не устраивает: видимо для инициализации hPaint, необходимо до прорисовки пользовательских сайтов сделать
дополнительный вызвов mapPaintByFrameToXImagePro, чтобы сайты с пользовательскими объектами нормально отрисовались.
Если его не сделать, то первый сайт затирает фон черным и рисует на нем свои объекты. Остальные сайты в оставшейся
области рисуются нормально.
Подскажите, пожалуйста, способ как обойтись без дополнительного вызова mapPaintByFrameToXImagePro, ибо если
фоновая карта большая, то даже при выключенных слоях прорисовка заметно тормозит.
Изменено: Андрей Сычев - 29.03.2019 11:49:21
 
К вопросу не относится, но.
Зачем вы копируете данные из QImage в XImageDesc ?? Вы же можете напрямую в QImage писать. То есть заставить вызов mapPaint* писать сразу в QImage.

В данном конкретном случае вы можете просто поле ximagedesc.Point выставить в bufferImage.constBits с const_cast-ом. Ну и поля в ximagedesc все правильно назначить, как в QImage
Изменено: Владимир Егоров - 29.03.2019 12:16:26
 
Печально, что за более чем 3 недели ответа по существу на поставленный вопрос так и не было.

Владимиру Егорову:
Спасибо за подсказку.
Конечно, можно было бы дать первому вызову mapPaintByFrameToXImagePro отрисоваться в буфер ximagedesc, а затем, вместо вызова memcpy, сделать замену буфера ximagedesc на буфер QImage. Правда, во-первых, у меня нет уверенности что если при уже созданном hPaint и прошедшем вызове mapPaintByFrameToXImagePro сделать такую подмену буферов, то ничего внутри gisapi не сломается. А во-вторых, существенного выигрыша по скорости при этом нет.
Вот тест:
Код
HPAINT hPaint = mapObj()->createPaintControl();
QTime time1_0 = QTime::currentTime();
HSELECT hSelect = mapCreateMapSelectContext(mapObj()->handle());
mapSelectLayer(hSelect, -1, 0);
QTime time1_1 = QTime::currentTime();
mapPaintByFrameToXImagePro(mapObj()->handle(), const_cast<XIMAGEDESC *>(&ximagedesc), -2,
                           const_cast<DFRAME *>(&frame), ximagedesc.Width, ximagedesc.Height,
                           0, hSelect, hPaint);
QTime time1_2 = QTime::currentTime();
memcpy(ximagedesc.Point, bufferImage.constBits(), bufferImage.byteCount());
qWarning() << "drawBackground:" << time1_0.msecsTo(time1_1) << time1_0.msecsTo(time1_2)
               << time1_0.msecsTo(QTime::currentTime());
А вот его результат: drawBackground: 0 83 83
Как видно, основное время ест вызов mapPaintByFrameToXImagePro (с выключенными слоями). На вызов memcpy уходит меньше миллисекунды.

Дополнительные вопросы разработчикам: почему даже при выключенных слоях вызов mapPaintByFrameToXImagePro занимает так много времени? И если уж нельзя от него совсем избавиться, то нет ли других способов его ускорить, кроме как слои поотключать?
Изменено: Андрей Сычев - 20.04.2019 14:14:26
 
Владимир Егоров:
По поводу QImage лучше уж создавать его на готовом буфере, чтобы не было теневого копирования (так более явно), ну и странный подход из constBits() убирать const. Есть же просто bits()


Андрей, насколько я правильно понял Ваши вопросы:
1. тормозит рисование даже при всех выключенных слоях. Какого размера буфер Вы пытаетесь заполнить?
2. первое рисование у выполняет заливку цветом вместо наложения.
 
Не понял что странного в использовании constBits(). Она делает только то что требуется: возвращает указатель на первый бит данных. При этом данные считаются константными, что во-первых, явно выражает намерения использовать их только для чтения, во-вторых, не дает ошибкам программы изменить буфер. Функция bits(), в отличие от нее, мало того что возвращает указатель на неконстантные данные, так еще и может выполнить глубокое копирование разделяемых данных, если, например, QImage был создан путем вызова конструктора QImage(const uchar * data, ...). Это все в справке по QImage написано.

Размер буфера не превышает размеров экрана. Данные примера из сообщения #3 были получены на экране размером 1280x1024. На другом компьютере с разрешением 1920х1080 поведение то-же.
Страницы: 1
Читают тему (гостей: 1)



© КБ Панорама, 1991-2024

Регистрируясь или авторизуясь на форуме, Вы соглашаетесь с Политикой конфиденциальности