본문 바로가기

프로그래밍/Delphi

웹페이지내 특정 Element를 이미지로 저장하기

웹페이지내에 이미지 링크가 실시간 로딩처리가 되는 경우 해당 IMG 태그에 해당하는 IHTMLImgElement의 이미지를 저장하는 방법을 고민해보고자 한다.

 

기본적으로 IE DOM 파서를 이용할 경우 해당 TAG에 해당하는 Element에 대해 IHTMLElement2 인터페이스를 이용하여 해당 TAG내부 HTML에 의해 IE 화면에 표시되는 부분을 이미지로 저장할 수 있다.

 

따라서 실시간으로 로딩되는 IMG태그 = IHTMLImgElement가 가지고 있는 이미지도 화면 캡쳐 없이 직접 저장이 가능해 진다

 

다음과 같이 IHTMLElement2 노드를 이미지로 변환하는 루틴을 만들어 보자

 

function TForm1.ElementAsBitmap(pElement : IHTMLElement2) : TBitmap;
var
  pRender       : IHTMLElementRender;
  oBmpPart      : TBitmap;
  nClientWidth  : Integer;
  nClientHeight : Integer;
  nX            : Integer;
  nLastX        : Integer;
  bDoneX        : Boolean;
  nY            : Integer;
  nLastY        : Integer;
  bDoneY        : Boolean;
begin
  Result := TBitmap.Create;

  try
    Result.Height := pElement.scrollHeight;
    Result.Width  := pElement.scrollWidth;
  except
    exit;
  end;

  LockWindowUpdate(Handle);

  if (pElement.QueryInterface(IID_IHTMLElementRender, pRender) = S_OK) then begin
    try
      oBmpPart        := TBitmap.Create;
      oBmpPart.Width  := pElement.scrollWidth;
      oBmpPart.Height := pElement.scrollHeight;
      nClientWidth    := pElement.clientWidth;
      nClientHeight   := pElement.clientHeight;

      try
        nX      := pElement.scrollWidth; 
        nLastX  := -1;
        bDoneX  := false;

        while not bDoneX do begin
          pElement.scrollLeft := nX;
          nX := pElement.scrollLeft;
          if nLastX = -1 then begin
            nLastX := nX + nClientWidth;
          end;
          nY     := pElement.scrollHeight;
          nLastY := (-1);
          bDoneY := false;

          while not bDoneY do 
          begin
            pElement.scrollTop := nY;
            nY := pElement.scrollTop;

            if nLastY = -1 then 
              nLastY := nY + nClientHeight;

            if (pRender.DrawToDC(oBmpPart.Canvas.Handle) = S_OK) then
              BitBlt(Result.Canvas.Handle, nX, nY, nLastX-nX, nLastY-nY, oBmpPart.Canvas.Handle, 2, 2,SRCCOPY);

            bDoneY  := (nY = 0);
            nLastY  := nY;
            Dec(nY, nClientHeight-4);  
          end;

          bDoneX  := (nX = 0);
          nLastX  := nX;
          Dec(nX, (nClientWidth-4));
        end;
      finally
        FreeAndNil(oBmpPart);
      end;
    finally
      pRender := nil;
    end;
  end;

  LockWindowUpdate(0);
end;

위 함수를 이용하여 다음과 같이 로딩된 페이지의 Body Element를 추적하여 본문을 이미지로 저장할 수 있다.

 

 

procedure TForm1.Button3Click(Sender: TObject);
var
  elm : IHTMLElement;
  bmp : TBitmap;
  fn : string;
begin
  elm := EwbCore1.Doc2.Body as IHTMLElement;
  bmp := ElementAsBitmap(elm as IHTMLElement2);
  fn := 'TEST_BODY.bmp';
  bmp.SaveToFile(fn);
  bmp.free;
end;

마찬가지로 실시간으로 로딩되는 IMG태그에 해당하는 IHTMLImgElement를 찾아내어 로딩된 이미지를 저장해 보자

// 지정된 아이디와 부분 매칭되는 img 태그를 찾아 이미지로 저장한다
procedure TForm1.Capture(Id : string; AFileName : string);
var
  elm : IHTMLElement;
  elc : IHTMLElementCollection;
  eli : Olevariant;
  i : integer;
  elimg, img : IHTMLImgElement;
  bmp : TBitmap;
begin
  elc := EwbCore1.Doc2.images as IHTMLElementCollection;
  for i := 0 to elc.length-1 do
  begin
    eli := i;
    elimg := elc.Item(eli, 0) as IHTMLImgElement;

    if Pos(Id, (elimg as IHTMLElement).Id)>0 then
    begin
      bmp := ElementAsBitmap(elimg as IHTMLElement2);
      bmp.SaveToFile(AFileName);
      bmp.free;

      StatusBar1.SimpleText := '캡쳐완료';
      Break;
    end;
  end;
end;