Что происходит с картинками при помещении в отчёты форматов FRX и FPX.

24.06.2015

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

Как и в прошлый раз, удалим для наглядности все бэнды, кроме заголовка. Растянем бэнд пошире и поместим на него картинку. Затем чуть выше вставленной картинки разместим заголовок. После этого поверх картинки помещаем текст с полупрозрачным фоном. Все эти операции проделываем в дизайнере отчётов и сохраняем сформированный шаблон отчёта.  У меня получился такой шаблон:

Отчёт с картинкой и текстом

Таблица, которую вы видите на экране - всего лишь картинка, вставленная в шаблон отчёта. Посмотрим как этот отчёт сохранился в шаблоне отчёта.

<?xml version="1.0" encoding="utf-8"?>
<Report ScriptLanguage="CSharp" ReportInfo.Created="05/21/2015 00:40:44" ReportInfo.Modified="05/21/2015 02:32:15" ReportInfo.CreatorVersion="1.0.0.0">
 <Dictionary/>
 <ReportPage Name="Page1">
 <ReportTitleBand Name="ReportTitle1" Width="718.2" Height="661.5">
 <PictureObject Name="Picture1" Left="18.9" Top="75.6" Width="670.95" Height="576.45" Image="iVBORw0KGgoAAAANSUhEUgAABHUAAAPTCAIAAACxEqIHAAAAAXNSR0IArs4c6QAAAAg=="/>
 <TextObject Name="Text1" Left="66.15" Top="28.35" Width="623.7" Height="18.9" Text="Everest instruction set" HorzAlign="Center" Font="Arial, 10pt, style=Bold"/>
 <TextObject Name="Text2" Left="94.5" Top="132.3" Width="330.75" Height="18.9" Border.ShadowColor="116, 0, 0, 0" Fill.Color="149, 255, 255, 255" Text="Yellow opcodes are reserved for future use." HorzAlign="Center" VertAlign="Center"/>
 </ReportTitleBand>
 </ReportPage>
</Report>
 

Сразу замечу: при формировании вышеприведённого XML кода я схитрил.  Посмотрите на свойство Image объекта PictureObject - не кажется ли оно подозрительно коротким? В оригинальном отчёте картинка, вставленная в отчёт, формирует строку длиной в  184770 символов, полученных трансформацией из 138499 байтовой картинки. Дело в том, что внутри отчёта картинка хранится в формате Base64; при такой конвертации картинка занимает больше памяти, но это цена, которую приходится платить за внедрение двоичных данных в формат XML. Размер шаблона отчёта составляет 186547 байт. В данном примере при внедрении картинки в шаблон отчёта, её размер увеличивается приблизительно на 33%.

Посмотрим, что получилось в подготовленном отчёте:

Предварительный просмотр отчёта

Размер подготовленного отчёте чуть снизился по сравнению с его шаблоном. Причина снижения в том, что подготовленный отчёт упакован с помощью gzip. Причина небольшого коэффициента компрессии в том, картинка в формате PNG уже сжата, а сжатые данные, даже если закодированы в base64, не дают высокого коэффициента сжатия.

Как и в шаблоне отчёта, перед публикацией кода подготовленного отчёта, я обрезаю свойство отчёта, содержащее упкакованное представление картинки.

<?xml version="1.0" encoding="utf-8"?>
<preparedreport>
 <pages>
 <page1>
 <b1>
 <p1 ImageIndex="0"/>
 <t1/>
 <t2/>
 </b1>
 </page1>
 </pages>
 <sourcepages>
 <ReportPage Name="Page1">
 <ReportTitleBand Name="ReportTitle1" Width="718.2" Height="661.5">
 <PictureObject Name="Picture1" Left="18.9" Top="75.6" Width="670.95" Height="576.45"/>
 <TextObject Name="Text1" Left="66.15" Top="28.35" Width="623.7" Height="18.9" Text="Everest instruction set" HorzAlign="Center" Font="Arial, 10pt, style=Bold"/>
 <TextObject Name="Text2" Left="94.5" Top="132.3" Width="330.75" Height="18.9" Border.ShadowColor="116, 0, 0, 0" Fill.Color="149, 255, 255, 255" Text="Yellow opcodes are reserved for future use." HorzAlign="Center" VertAlign="Center"/>
 </ReportTitleBand>
 </ReportPage>
 </sourcepages>
 <dictionary>
 <b1 name="Page0.ReportTitle1"/>
 <p1 name="Page0.Picture1"/>
 <page1 name="Page0"/>
 <t1 name="Page0.Text1"/>
 <t2 name="Page0.Text2"/>
 </dictionary>
 <bookmarks/>
 <outline/>
 <blobstore>
 <item Stream="iVBORw0KGgoAAAANSUhEUgAABHUAAAPTCAIAAACxEqIHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADr4AAA6+AepCscg=="/>
 </blobstore>
</preparedreport>
 

 Настало время открыть маленькую тайну: как же на самом деле происходит печать, отрисовка или конвертация отчёта из подготовленного отчёта. Страницы подготовленного отчёта находятся в секции <pages>. В данном <pages> это контейнер, содержащий страницы подготовленного отчёта <page1>. При печати отчёта для получения свойств страницы, генератор отчётов поступает следующим образом: ищет одноимённый тэг в секции <dictionary> и получает имя элемента отчёта. Полученное имя используется для обращения к шаблонным элементам отчёта, содержащих общие свойства для всех ссылающихся на них элементов.

Есть во всей этой схеме одна тонкость: в секции <sourcepages> вы не найдёте страницу с именем Page0, а в секции <dictionary> нет ни одной ссылки на Page1. Хитрость заключается в том, что при использовании словаря для нахождения соответствия элемента подготовленного отчётов элементу шаблона отчёта, номер страницы необходимо увеличить на единицу. Поясню на примере - если нам неходимо получить базовые атрибуты элемента <page1>, то находим его в секции <dictionary>, и из свойства Name получаем имя этого элемента в секции <souurcepages>. В случае, если элемент является страницей отчёта, при поиске соответствия меняем Page0 на Page1. О причинах такого поведения будет рассказано в другой раз, пока же примите необходимость подмены номера как данность.

Обратите внимание на свойство Image элемента <PictureObject>. Заметили, что это свойство исчезло у объекта <PictureObject> подготовленного отчёта? Свойство Image, которое содержит данные картинки, переместилось в секцию <blobstore>, при этом элемент <PictureObject> подготовленного отчёта описывает лишь свойства картинки, но уже не содержит графические данные. Для использования картинки в подготовленном отчёте используется элемент <p1> и его свойство ImageIndex. При печати подготовленного отчёта происходит следующее - объект <p1> находится в секции <dictionary> и по его имени находится ссылка на подходящий элемент <PictureObject>, из которого выбираются базовые свойства картинки - размер, позиция и т.д.

Свойство ImageIndex элемента <p1> указывает на двоичные данные в секции <blobstore>. Эта секция состоит из множества элементов <item>, свойство Stream которых содержит образ картинки. Свойство ImageIndex определяет порядковый номер элемента <item>.

Теперь вы имеете неплохое представление о внутренней структуре шаблона отчёта и подготовленного отчёта. В следующий раз мы чуть более внимательно посмотрим на свойства какого-нибудь элемента отчёта.

 

 

 

20 ноября 2024

Локализация и смена языков в FastReport VCL

FastReport VCL поддерживает 40 языков для локализации интерфейса и позволяет изменять язык на лету через меню или код, без перекомпиляции.
1 ноября 2024

Новые возможности редактора отчетов FastReport VCL

Рассматриваем новые возможности редактора отчетов: выносные линии, подсветка пересекающихся объектов, обновлённые деревья отчетов и данных.
30 октября 2024

Использование стилей при создании отчетов в FastReport VCL

В статье подробно рассматривается одна из новых возможностей FastReport VCL – применение стилей и страниц стилей.