Возвращает сгенерированное Delphi растровое изображение в (ASP).Net через COM-объект

#.net #delphi #com #bitmap #com-interop

#.net #delphi #com #растровое изображение #com-взаимодействие

Вопрос:

Мы создаем веб-приложение, которое будет отображать контурные области в виде растровых изображений в интерфейсе браузера.

У нас уже есть обширная библиотека Delphi, которая может генерировать контуры и рисовать их на TCanvas. Мы хотели бы иметь возможность повторно использовать этот код как можно чаще.

Итак, мы создали COM-объект в Delphi и используем его для создания контуров. Я добавил ссылку на этот COM-объект в свой ASP.Net проект, чтобы я мог получить к нему доступ из .Сетевой код. Пока, похоже, это работает хорошо.

Проблема, с которой я сталкиваюсь сейчас, заключается в получении сгенерированного TBitmap в ASP.Чистая сторона вещей, как можно быстрее.

Я могу придумать несколько сценариев, но в каждом из них я сталкиваюсь с проблемами:

  1. Сохраните растровое изображение в stream (как PNG) и верните IStream интерфейс. Проблема в том, что мастер создания COM-объектов, похоже, не принимает IStream в качестве возвращаемого значения для функции. Кроме того, я не знаю, если .Net будет знать, что с ним делать, но я надеюсь, что оболочка взаимодействия позаботится об этом.

  2. Сохраните растровое изображение в stream (как PNG) и верните массив байтов. Какой возвращаемый тип я должен использовать тогда? Я предполагаю SAFEARRAY(byte) (по крайней мере, мастер принимает это), но а) как мне создать SAFEARRAY на стороне Delphi и б) как мне это прочитать в .Net?

  3. Каким-то образом преобразуйте TBitmap в IPicture интерфейс и верните его. По крайней мере, IPicture, похоже, поддерживается мастером создания COM-объектов. Здесь я действительно не знаю, как преобразовать TBitmap в IPicture (за исключением сохранения его в stream и создания IPicture из этого stream, что кажется немного глупым, поскольку .Сетевому коду в любом случае придется передавать его в браузер). Опять же, я понятия не имею, как .Net обработает это IPicture , хотя я надеюсь, что оно отобразит его в обычный Image объект, который затем можно будет записать через Response объект.

Итак, мой вопрос таков: каков был бы наилучший способ продвижения вперед с точки зрения производительности и как решить указанные проблемы?

Ответ №1:

Я бы передал HBITMAP между собственным и управляемым мирами.

  • Отсоедините дескриптор от Delphi TBitmap путем вызова ReleaseHandle .
  • Создайте .net Bitmap путем вызова Image.FromHbitmap() .

Комментарии:

1. Я пытаюсь выполнить то же самое, и это будет отлично работать для in process COM, но не для out of process COM . Я пока не нашел простого решения для out of process COM.

2. @dschaeffer Вам нужно сериализовать изображение в поток байтов или что-то подобное

Ответ №2:

Вы могли бы написать COM-объект Delphi, которому принадлежит растровое изображение и который может возвращать дескриптор растрового изображения. Вы можете получить этот дескриптор из TBitmap и преобразовать его в OLE_HANDLE. Пока вы сохраняете ссылку на COM-объект, растровое изображение будет действительным.

Комментарии:

1. Интересно. Могу ли я затем использовать Bitmap. Из BITMAP с помощью OLE_HANDLE?

2. проще просто вызвать ReleaseHandle и передать право собственности

3. Согласно MSDN, изображение. FromHbitmap() фактически создает копию изображения. Я никогда не пробовал это, но, вероятно, вам даже не нужно сохранять исходное растровое изображение.

4. Нет, это неправильно. В документации об этом не говорится, фактически говорится: «Однако вам не следует удалять растровое изображение GDI или палитру GDI до тех пор, пока объект GDI Bitmap не будет удален или не выйдет за пределы области видимости». Это явно подразумевает, что растровый объект .net поддерживается исходной HBitmap. Отпустите дескриптор, за которым следует изображение. Можно использовать FromHbitmap.

5. Возможно, я что-то пропустил, но раздел «Примечания» msdn.microsoft.com/en-us/library/k061we7x.aspx четко указано: метод FromHbitmap создает копию растрового изображения GDI; таким образом, вы можете освободить входящее растровое изображение GDI с помощью метода GDI DeleteObject сразу после создания нового изображения.