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

XIMAGEDESC - получение изображения

Поиск  Пользователи  Правила  Войти
Форум » Настольные приложения » GIS ToolKit, GIS ToolKit Active, ГИС Конструктор для Windows
Страницы: Пред. 1 2 3 4 След.
RSS
XIMAGEDESC - получение изображения
 
Коллеги, я прошу дать ответ.
Так же, я выкладываю Вам демо пример. Пример формирует 2 изображения. 2.bmp - это изображение, полученное путем декодированием массиа з Gis системы, 3.bmp - это изобюражение, декодирование из изображения 1.bmp.
Для формирования изображений, выполняется  указанный Вами алгоритм. Так же, я прошу сообщить мне адрес электронной почты для отправки Вам официального запроса. Спс.
https://disk.yandex.ru/d/NTD1dFCwC7eSIA

Изменено: George - 01.07.2022 11:09:41
 
Здравствуйте!

Официальный запрос можно отправить на почту технической поддержки panorama@gisinfo.ru. В письме укажите, пожалуйста, название организации и номер лицензионного ключа.
 
Цитата
Alexander Volovikov написал:
Для формирования изображений, выполняется  указанный Вами алгоритм.

Посмотрел Ваш код.
В Вашем примере карта открывается, буфер изображения создается и потом выводится в файл.
Пропущено главное - заполнение этого буфера изображением карты.

Ранее я Вам давал пример работы с функцией mapViewImageToXImage.
Как можно заметить из параметров, принимаемых этой функцией, она про карту ничего не знает.
На вход ей передается идентификатор буфера изображения (HIMAGE), а не идентификатор открытых пространственных данных (HMAP).
Чтобы что-то отрисовать в буфер изображения надо воспользоваться функцией mapDrawImageMap.

Либо вместо mapViewImageToXImage использовать mapPaintToXImage, которая сразу заполняет XIMAGEDESC из карты (HMAP). А лучше воспользоваться более новыми функциями:

Цитата
 // Вывести изображение карты в XImage (массив)
 // Данная функция реализована для XWindow !
 // Описание структуры XIMAGEDESC в maptype.h
 // erase - признак стирания фона перед выводом,
 //        (-2 - рисовать поверх текущего изображения в буфере)
 // x,y - координаты левого верхнего угла внутри
 // битовой области XImage для размещения изображения
 // rect - выводимый фрагмент карты
 // При ошибке в параметрах возвращает ноль

_MAPIMP long int _MAPAPI mapPaintToXImageProL(HMAP hMap, XIMAGEDESC * imagedesc, long int erase,
                                             long int x, long int y, LRECT * rect, HPAINT hPaint);

_MAPIMP long int _MAPAPI mapPaintToXImagePro(HMAP hMap, XIMAGEDESC * imagedesc, long int erase,
                                           long int x, long int y, RECT * rect, HPAINT hPaint);
 
Еще пара замечаний по тексту.

Цитата
   
   // Открыть карту
   [DllImport("gis64acces.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]

Почему указывается стандарт вызова CallingConvention.Cdecl?
Судя по имени DLL, это код для Windows. В Windows MAPAPI соответствует стандарту вызова WINAPI, то есть stdcall!

И почему для одних функций указывается стандарт вызова, а для других нет (то есть используется стандарт по умолчанию для проекта)?
 
Спасибо!
Функции "mapPaintToXImageProL" и "mapPaintToXImagePro" не вызываются. Идет ошибка.
Функция "mapPaintToXImage" вызывается. Но рузультат прежний.

Позвольте Вам продемонстрировать, кусок кода Qt приложения
Код
void MapWidget::DrawMap(QPainter* p, int cx, int cy, int cw, int ch)
{
  if (MapHandle)
  {
    RECT rectDraw;
    rectDraw.left = cx;
    rectDraw.top = cy;
    rectDraw.right = cx + cw;
    rectDraw.bottom = cy + ch;

    if (BitMap)
    {
      XIMAGEDESC xImageDesc;
      xImageDesc.Point = BitMap;                     // Àäðåñ íà÷àëà îáëàñòè ïèêñåëîâ
      xImageDesc.Width = cw;                         // Øèðèíà ñòðîêè â ïèêñåëàõ
      xImageDesc.Height = ch;                        // ×èñëî ñòðîê
      xImageDesc.Depth = MAPDEPTH;                   // Ðàçìåð ýëåìåíòà â áèòàõ (8,15,16,24,32)
      xImageDesc.CellSize = BMCELLSIZE;              // Ðàçìåð ýëåìåíòà(ïèêñåëà) â áàéòàõ
      xImageDesc.RowSize = cw * xImageDesc.CellSize; // Øèðèíà ñòðîêè â áàéòàõ

      RECT mapRect;
      mapRect.left = cx - ScrollArea->horizontalScrollBar()->value();
      mapRect.top = cy - ScrollArea->verticalScrollBar()->value();
      mapRect.right = mapRect.left + cw;
      mapRect.bottom = mapRect.top + ch;

      POINT mapPositionInMapImage;
      mapPositionInMapImage.x = 0;
      mapPositionInMapImage.y = 0;

      if (!ObjectHandle)
      {
        ObjectHandle = mapCreateObject(MapHandle);
        mapRegisterDrawObject(ObjectHandle, 5, LOCAL_VECTOR);

        mapAppendPointPlane(ObjectHandle, 6220600, 7445000);
        mapAppendPointPlane(ObjectHandle, 6220600, 7445100);

        IMGGRAPHICMARKEX graphicMark;
        memset(&graphicMark, 0, sizeof(graphicMark));
        graphicMark.Length = sizeof(graphicMark);
        StrCopy(graphicMark.Name, "/usr/share/gisdesigner/examples/myfirst/bus.png", sizeof(graphicMark.Name));
        graphicMark.Type = 0;  // Òèï ôàéëà (0 - PNG, 1 - BMP, 2 - JPG...
        graphicMark.Width = PIX2MKM(64);
        graphicMark.Height = PIX2MKM(21);
        graphicMark.PosV = PIX2MKM(10);
        graphicMark.PosH = PIX2MKM(32);
        graphicMark.Rotate = 1;  // Óñòàíîâêà âîçìîæíîñòè ïîâîðîòà
        mapAppendDraw(ObjectHandle, IMG_GRAPHICMARK, (char *)&graphicMark);
        mapReadObjectByKey(MapHandle, MapHandle, ObjectHandle, 1, 103959);
      }

      mapClearImageObjects(hScreen, 0);

      if (mapViewImageToXImage(hScreen, &xImageDesc, &mapRect, &mapPositionInMapImage))
      {
          QImage image((uchar *)BitMap, cw, ch, QImage::Format_RGB32);
          p->drawImage(cx, cy, image, 0, 0, cw, ch);
          image.save("C:/test.png");
      }
    }
  }
}
Обращаю Ваше внимание, на то, что тут используется именно функция "mapViewImageToXImage"
Кусок кода из примера. Если выше исключить "ObjectHandle", то получаем аналогично. Почему (я проверить не могу) для QT примера последовательность корректная, а для C# примера - нет?

Код
 /// <summary>
    /// Вариант создания изображения с использованием структуры <see cref="XIMAGEDESC"/>
    /// </summary>
    public static XIMAGEDESC CreateXImage(int Heiht, int Width)
    {
        var hMap = mapOpenDataUn(@"reg_russia.sitx", 0);
        var bitmapHandle = mapCreateImageEx(Width, Heiht);
        mapGetViewType(hMap);

        // Описание изображение
        var imageInfo = new XIMAGEDESC()
        { Depth = 32, Width = Width, Height = Heiht, CellSize = 32 / 8 };

        imageInfo.RowSize = imageInfo.CellSize * imageInfo.Width;
        var size = GetSize(imageInfo);

        // Определяем ссылку на массив
        var pointer = Marshal.AllocHGlobal(size);
        imageInfo.Point = pointer;

        // Размер изображения
        var rectInfo = new RECT() { left = 0, right = imageInfo.Width, bottom = imageInfo.Height, top = 0 };
        var pointInfo = new POINT() { x = 0, y = 0 };

        var result = mapViewImageToXImage(bitmapHandle, ref imageInfo, ref rectInfo, ref pointInfo);
        return imageInfo;
    }
 
Пример вызова функции mapPaintToxImagePro

Изменено: Денис Вицко - 06.07.2022 08:27:23 (исправил вставку картинок)
 
Цитата
Alexander Volovikov написал:
Пример вызова функции  mapPaintToxImagePro

Во-первых, параметр hPaint - это совсем не bitmapHandle, который Вы получаете от mapCreateImageEx. hPaint - это контекст отображения для многопоточного вызова.
Цитата
_MAPIMP long int _MAPAPI mapPaintToXImagePro(HMAP hMap, XIMAGEDESC * imagedesc, long int erase,
                                          long int x, long int y, RECT * rect, HPAINT hPaint);
В однопоточном режиме туда можно передать ноль, иначе этот контекст надо сначала создать, а по окончании использования удалить:

Цитата

// Создать/Удалить контекст отображения для многопоточного вызова
// функций mapPaintByFramePro или mapPaintByFrameToXImagePro
// hmap - идентификатор открытых данных
// hpaint - контекст отображения для копирования параметров отображения\печати или 0
// Для каждого потока создается свой контекст и передается в качестве параметра функции
// В каждом контексте создается свой буфер отображения и выделяется память под служебные области
// Размер резервируемой памяти помимо буфера отображения может занимать 1-2 Мбайта,
// внутренний буфер отображения для размера 1920x1080 занимает 8 Мбайт
// Размер может устанавливаться программно - mapSetMaxScreenImageSize
// При ошибке возвращает ноль

_MAPIMP HPAINT _MAPAPI mapCreatePaintControlEx(HMAP hmap, HPAINT hpaint);
_MAPIMP HPAINT _MAPAPI mapCreatePaintControl(HMAP hmap);
_MAPIMP void _MAPAPI mapFreePaintControl(HPAINT hPaint);


Во-вторых, проверьте стандарт вызова в Вашем прототипе функции. Как я писал выше, подменять WINAPI (STDCALL) на CDECL недопустимо, как и наоборот. Будет AV либо при обращении к функции, либо при выходе из области видимости, когда будет очищаться память параметров функции.
 
Цитата
Alexander Volovikov написал:
Обращаю Ваше внимание, на то, что тут используется именно функция "mapViewImageToXImage"
Кусок кода из примера.
Если выше исключить "ObjectHandle", то получаем аналогично. Почему (я проверить не могу) для QT примера последовательность корректная, а для C# примера - нет?

Вы не внимательно посмотрели работу представленного Вам примера, а также проигнорировали мой ответ выше:

Цитата
Денис Вицко написал:
Ранее  я Вам давал пример  работы с функцией mapViewImageToXImage.
Как можно заметить из параметров, принимаемых этой функцией, она про карту ничего не знает.На вход ей передается идентификатор буфера изображения (HIMAGE), а не идентификатор открытых пространственных данных (HMAP).Чтобы что-то отрисовать в буфер изображения надо воспользоваться функцией mapDrawImageMap.

Еще раз.
Функция mapViewImageToXImage честно выдаст Вам заполненную структуру XIMAGEDESC по той информации, которая заполнена в HIMAGE.
Вы HIMAGE создали, но поскольку он никем и ничем не заполнялся, передав пустой HIMAGE в функцию mapViewImageToXImage, на выходе Вы закономерно получаете пустой буфер в XIMAGEDESC.
Если Вы хотите получить в XIMAGEDESC изображение карты, его надо сначала положить в HIMAGE. За это отвечает функция mapDrawImageMap.
Вызова mapDrawImageMap я в Вашем коде не вижу.
 
Спасибо. Стандарты вызова исправил, конечно.
Последовательность вызовов должна быть такой:
  1. mapCreateImageEx -> hImage
  2. mapGetViewType
  3. mapDrawImageMap
  4. mapViewImageToXImage

    В такой последовательности корректно?
 
Цитата
Alexander Volovikov написал:
В такой последовательности корректно?

В общем - да.

Не ясно зачем вызов mapGetViewType, если Вы ничего не делаете с полученной информацией.
Возможно, стоит установить вид карты как принтерный растровый (VT_PRINTRST), чтобы изображение было таким же как в ГИС Панорама по умолчанию (mapSetViewType(hMap, 6))

В остальном все верно, только не забывайте по окончании использования с помощью соответствующих функций освобождать полученные HIMAGE, HMAP и прочие указатели, выделенные в ГИС-ядре.
Это неуправляемый код. Ваш "сборщик мусора" не освободит выделенную в ГИС-ядре память.

Цитата
 // Запросить/Установить способ отображения карты
 // hmap - идентификатор открытых данных
 // При установке нового способа отображения возвращается
 // предыдущее значение
 // (см. maptype.h : VT_SCREEN(1), VT_PRINT(3), VT_PRINTRST(6),...)
 // При ошибке возвращает ноль

_MAPIMP long int _MAPAPI mapGetViewType(HMAP hmap);
_MAPIMP long int _MAPAPI mapSetViewType(HMAP hmap, long int type);
_MAPIMP long int _MAPAPI mapSetViewTypePro(HMAP hmap, long int type, HPAINT hPaint);
Страницы: Пред. 1 2 3 4 След.
Читают тему (гостей: 1)



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

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