Здравствуйте! Нужна ваша помощь. Требуется скопировать в 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, ибо если фоновая карта большая, то даже при выключенных слоях прорисовка заметно тормозит.
К вопросу не относится, но. Зачем вы копируете данные из QImage в XImageDesc ?? Вы же можете напрямую в QImage писать. То есть заставить вызов mapPaint* писать сразу в QImage.
В данном конкретном случае вы можете просто поле ximagedesc.Point выставить в bufferImage.constBits с const_cast-ом. Ну и поля в ximagedesc все правильно назначить, как в QImage
Печально, что за более чем 3 недели ответа по существу на поставленный вопрос так и не было.
Владимиру Егорову: Спасибо за подсказку. Конечно, можно было бы дать первому вызову mapPaintByFrameToXImagePro отрисоваться в буфер ximagedesc, а затем, вместо вызова memcpy, сделать замену буфера ximagedesc на буфер QImage. Правда, во-первых, у меня нет уверенности что если при уже созданном hPaint и прошедшем вызове mapPaintByFrameToXImagePro сделать такую подмену буферов, то ничего внутри gisapi не сломается. А во-вторых, существенного выигрыша по скорости при этом нет. Вот тест:
А вот его результат: drawBackground: 0 83 83 Как видно, основное время ест вызов mapPaintByFrameToXImagePro (с выключенными слоями). На вызов memcpy уходит меньше миллисекунды.
Дополнительные вопросы разработчикам: почему даже при выключенных слоях вызов mapPaintByFrameToXImagePro занимает так много времени? И если уж нельзя от него совсем избавиться, то нет ли других способов его ускорить, кроме как слои поотключать?
Владимир Егоров: По поводу QImage лучше уж создавать его на готовом буфере, чтобы не было теневого копирования (так более явно), ну и странный подход из constBits() убирать const. Есть же просто bits()
Андрей, насколько я правильно понял Ваши вопросы: 1. тормозит рисование даже при всех выключенных слоях. Какого размера буфер Вы пытаетесь заполнить? 2. первое рисование у выполняет заливку цветом вместо наложения.
Не понял что странного в использовании constBits(). Она делает только то что требуется: возвращает указатель на первый бит данных. При этом данные считаются константными, что во-первых, явно выражает намерения использовать их только для чтения, во-вторых, не дает ошибкам программы изменить буфер. Функция bits(), в отличие от нее, мало того что возвращает указатель на неконстантные данные, так еще и может выполнить глубокое копирование разделяемых данных, если, например, QImage был создан путем вызова конструктора QImage(const uchar * data, ...). Это все в справке по QImage написано.
Размер буфера не превышает размеров экрана. Данные примера из сообщения #3 были получены на экране размером 1280x1024. На другом компьютере с разрешением 1920х1080 поведение то-же.