понеділок, 15 липня 2013 р.

Вставка картинки в HTML

Здається, що тут може бути нового? Чому, і головне, навіщо тут піднято це питання? Під час роботи над одним Delphi-проектом виникла необхідність виводити HTML-текст з зображенням без формування зовнішнього файлу - картинка повинна зберігатися в тілі документу.
Відразу хочеться банально написати щось типу такого:

 <img alt="name" height="32" src="image.jpg" width="32" />

 То що можна запропонувати як альтернативу?

Спочатку виникла думка копати в сторону SVG, але в результаті формується файл xml, з яким також щось потрібно робити. Притому, наявні конвертори скалярної у векторну графіку не забезпечують достатньої якості картинки.
Другий варіант - брутальний, створити таблицю без рамок з коміркою розміром в 1px, заливаючи її в потрібний колір:

...
...
...

Без довгих роздумів пишемо код на FireMonkey:

function TImageToHtml_fm_Main.ColorToHtml(aColor: TAlphaColor): string;
begin
  if (TAlphaColorRec(aColor).R = 0) and
     (TAlphaColorRec(aColor).G = 0) and
     (TAlphaColorRec(aColor).B = 0) then
    Result := Format('#%.2x%.2x%.2x', [TAlphaColorRec(ComboColorBox1.Color).R, TAlphaColorRec(ComboColorBox1.Color).G, TAlphaColorRec(ComboColorBox1.Color).B])
  else
    Result := Format('#%.2x%.2x%.2x', [TAlphaColorRec(aColor).R, TAlphaColorRec(aColor).G, TAlphaColorRec(aColor).B]);
end;

procedure TImageToHtml_fm_Main.ImageControl1Change(Sender: TObject);
const
  C_STYLE = '<style>  td{'                    +
                        'height:1px;'         +
                        'width:1px;'          +
                        'border-style:none;'  +
                        'padding:0px;'        +
                        '}'                   +
            '</style>';
  C_TABLE = '<table cellspacing="0" cellpadding="0" cols="%d">';
var
  loBitMapData  : TBitmapData;
  loCurrColor   : TAlphaColor;
  sCurrColor    : string;
  sText         : string;
  x             : Integer;
  y             : Integer;
begin
  Memo1.Lines.Clear;
  if ImageControl1.Bitmap.Map(TMapAccess.maRead, loBitMapData) then
  begin
    sText := C_STYLE + sLineBreak + '<div>' + Format(C_TABLE, [Trunc(ImageControl1.Bitmap.Width)]) + sLineBreak;
    for y := 0 to Trunc(ImageControl1.Bitmap.Height) - 1 do
    begin
      sText := sText + '<tr>';
      for x := 0 to Trunc(ImageControl1.Bitmap.Width) - 1 do
      begin
        loCurrColor := loBitMapData.GetPixel(x, y);
        sCurrColor := ColorToHtml(loCurrColor);
        sText := sText + '<td bgcolor="' + sCurrColor + '"></td>'
      end;
      sText := sText + '</tr>' + sLineBreak;
    end;
    sText := sText + '</table></div>';
    ImageControl1.Bitmap.Unmap(loBitMapData);
  end;
  Memo1.Lines.Text := sText;
end;

Завантажити весь проект.
В результаті можна отримати щось аналогічне:


Відразу маса недоліків:
  • відсутня прозорість;
  • великий розмір, що зростає пропорційно розмірам вихідного зображення:
  • неможливість використовувати картинку в стилях. 
Хоча є і сумнівний плюс - її неможливо скопіювати або зберегти на диск.

І от якось мандруючи шляхами Інтернету, наткнувся на ще один метод - передача будь-якої інформації через url. Дані кодуються в base64 і не повинні перевищувати 32768 байтів. Можна написати свій конвертор або скористатися існуючим. В результаті отримуємо робочий стиль, який придатний для використання для картинки розміром 32х32 точки:


div.my_name{width:32px;height:32px;border:none;background-image:url(data:image/png;base64, зображення_в_кодуванні_base64);}

Використання в коді HTML:
<div class="my_name">
Зображення виглядає тепер значно краще, миліше нашим очам:



Однозначні переваги:
  • використання стилів, що дає можливість використання зображення необмежену кількість разів без суттєвого збільшення коду;
  • коректне відображення прозорості;

До мінусів слід віднести лише невеликий максимальний розмір зображення в 32 КБайти.

Стаття написана у співпраці з Юрою Степанцем, який своєю рукою і гострим зором спрямовував мене в потрібне русло.

Немає коментарів :

Дописати коментар