Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: What is the best way to insert an image into a RTF file?


This question is answered. Helpful answers available: 0. Correct answers available: 1.


Permlink Replies: 13 - Last Post: Mar 4, 2016 9:32 AM Last Post By: Nathan Webers
Nathan Webers

Posts: 15
Registered: 8/20/06
What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 25, 2016 7:03 AM
Hello,

I have been searching around for a way to programmatically insert an image into an RTF file using Delphi. Does anyone know of a method that allows this?

Thanks,
Nate
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: What is the best way to insert an image into a RTF file?
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 25, 2016 10:44 AM   in response to: Nathan Webers in response to: Nathan Webers
Nathan Webers wrote:

Hello,

I have been searching around for a way to programmatically insert an
image into an RTF file using Delphi. Does anyone know of a method
that allows this?

With or without involvement of a TRichedit control? If you have the
rich text document in a control the simplest way to insert a graphic
into it is in fact to copy the graphic to the clipboard and use the
controls PasteFromClipboard method to insert the graphic at the current
caret position.


--
Peter Below
TeamB

Nathan Webers

Posts: 15
Registered: 8/20/06
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 25, 2016 1:11 PM   in response to: Peter Below in response to: Peter Below
{quote:title=Peter Below wrote:}
With or without involvement of a TRichedit control?...

I suppose I could use a TRichedit control. Basically, what I want to do is find some text in an RTF document that I would use as a flag and replace that text with an image.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: What is the best way to insert an image into a RTF file?
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 25, 2016 1:40 PM   in response to: Nathan Webers in response to: Nathan Webers
Nathan wrote:

I suppose I could use a TRichedit control.

You could, but it is not trivial to implememt. You would have to use the
EM_GETOLEINTERFACE message to retreive the RichEdit's IRichEditOle interface,
and then call the IRichEditOle::InsertObject() method. But that involves
implementing the IOleObject, IStorage, and IOleClientSite interfaces (you
can get an IOleObject for a file using OleUIInsertObject() or OleCreateFromFile()).

Robert Dunn has some nice wrappers for this functionality:

http://yacs.lebeausoftware.org

For example, his TaeRichEdit component has an InsertObject() method that
prompts the user for a file. And he has a TIRichEditOle wrapper class that
has an InsertBitmap() method for inserting a VCL TBitmap object into a TaeRichEdit.

Basically, what I want to do is find some text in an RTF document
that I would use as a flag and replace that text with an image.

You could use the RichEdit's FindText() method to find the text, then use
its SelStart and SelLength properties to highlight the text, and then use
IRichEditOle::InsertObject() to replace the selection with the image object.

--
Remy Lebeau (TeamB)
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 26, 2016 11:00 AM   in response to: Nathan Webers in response to: Nathan Webers
Nathan Webers wrote:

{quote:title=Peter Below wrote:}
With or without involvement of a TRichedit control?...

I suppose I could use a TRichedit control. Basically, what I want to
do is find some text in an RTF document that I would use as a flag
and replace that text with an image.

You could certainly modify the rich text file directly, but that
requires an in-depth knowledge of the rich text format, and how binary
date like a bitmap image has to be coded to be inserted. See
https://msdn.microsoft.com/en-us/library/aa140283%28v=office.10%29.aspx#
rtfspec_24 if you feel adventureous and have a month or so of idle time
at your hand <g>.

--
Peter Below
TeamB

Roy Lambert

Posts: 1,063
Registered: 8/7/01
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 28, 2016 5:03 AM   in response to: Peter Below in response to: Peter Below
Peter

if you feel adventureous and have a month or so of idle time
at your hand <g>.

You are thinking of just the picture bit here I assume. If its the whole rtf you're an order of magnitude or two out :)

Roy
Nathan Webers

Posts: 15
Registered: 8/20/06
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 25, 2016 1:52 PM   in response to: Nathan Webers in response to: Nathan Webers
What about converting an image to HEX and then inserting the necessary tags and the HEX into the RTF file?

This is the route that I have been chasing, but I'm having a hard time getting a TImage converted into the HEX to begin with.
Roy Lambert

Posts: 1,063
Registered: 8/7/01
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 26, 2016 12:14 AM   in response to: Nathan Webers in response to: Nathan Webers
Nathan

I'm probably being very thick here but as I understand your question what you want to do is, without using a visual control change a marker in an rtf file into something else (in this case an image).

This is where I demonstrate I'm thick. An rtf file is simply a collection of bytes. Create two rtf documents, one with the marker text, and one with the image. Open in a hex editor and spot the differences, or you can use Delphi to analyse the two. Those will give you what to search for and what to use as a template. Then it should be a simple matter of load the file into something suitable (maybe a string stream) and do the replacement then save back.

The biggest proble with working with rtf is understanding the specification and what's needed to achieve something. Hopefully, in your case you don't need much understanding - just enough for the mechanics

Roy Lambert

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 26, 2016 9:51 AM   in response to: Roy Lambert in response to: Roy Lambert
Roy wrote:

This is where I demonstrate I'm thick. An rtf file is simply a
collection of bytes. Create two rtf documents, one with the
marker text, and one with the image. Open in a hex editor
and spot the differences, or you can use Delphi to analyse
the two.

RTF is actually formatted in plain text, so any text editor or diff viewer
will be easier to use then a hex editor.

--
Remy Lebeau (TeamB)
Roy Lambert

Posts: 1,063
Registered: 8/7/01
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 28, 2016 5:06 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy

RTF is actually formatted in plain text, so any text editor or diff viewer
will be easier to use then a hex editor.

I wasn't sure what happened with graphics so a hex editor is playing it safe. If I had to do it I'd probably write a simple comparison program

Roy
Nathan Webers

Posts: 15
Registered: 8/20/06
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2016 7:15 AM   in response to: Nathan Webers in response to: Nathan Webers
Through some more digging I was able to devise a way to programmatically add an image to an RTF file. The method I devised is one that directly changes the content of the RTF file without having to use a RichEdit box, or deprive the user of their copy buffer.

Basically, I do the following:

1) Load the image as a filestream.
2) Convert the image from binary to hex and store the hex in a string.
3) Determine the width and height of the image in question through the use of separate functions (depends on the type of image) that gives me the result of width and height in units of twips (1/1440th of an inch).
4) Construct a string that contains the necessary flags (the "pict" flag, what type of image, width in twips, height in twips) for an image in an RTF and then inserts the string containing the hex for the image into the larger string.
5)Load the RTF file into a string list and then do a string-replace on the text of the file, replacing the targeted text with the complete string for the image. Then save the changed file.

I can get this to work fine with JPEG and PNG, but I am actually having a little trouble with bitmaps. However, I think it's just a matter of figuring out the flags for handling the bitmap (there are several). I may have to convert the bitmap to a metafile and then just use the metafile flag, instead.

Thanks for all of the suggestions as they were helpful!
Roy Lambert

Posts: 1,063
Registered: 8/7/01
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2016 7:46 AM   in response to: Nathan Webers in response to: Nathan Webers
Nathan

When you have it all figured out can you post the code for the rest of us please.

Roy Lambert

Nathan Webers

Posts: 15
Registered: 8/20/06
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2016 8:12 AM   in response to: Roy Lambert in response to: Roy Lambert
Roy Lambert wrote:
Nathan

When you have it all figured out can you post the code for the rest of us please.

Roy Lambert


Sure. I want to clean up my code a bit as well :)
Nathan Webers

Posts: 15
Registered: 8/20/06
Re: What is the best way to insert an image into a RTF file?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 4, 2016 9:29 AM   in response to: Nathan Webers in response to: Nathan Webers
My boss said not to worry about bitmaps as JPEG suits his needs :). As promised, here is the code that does the substitution of a string to replace with a string that consists of an image (JPG or PNG) while not using a rich edit box or deprive the user of their copy/paste clipboard buffer:
////////////////////////////////////////////////////////////////////////////////
procedure GetJPGDimensions(const sFile: string; var wWidth, wHeight: word);
{Returns the width and height of the jpeg file}
var
  JpegImg: TJpegImage;
begin
  JpegImg := TJpegImage.Create;
  JpegImg.LoadFromFile(sFile);
  wWidth := JpegImg.Width;
  wHeight := JpegImg.Height;
  JpegImg.Free;
end;
 
////////////////////////////////////////////////////////////////////////////////
procedure GetPNGDimensions(const sFile: string; var wWidth, wHeight: word);
{Returns the width and height of the png file}
var
  pngPNGImage : TPNGImage;
 
begin
  pngPNGImage := TPNGImage.Create;
  pngPNGImage.LoadFromFile(sFile);
  wWidth := pngPNGImage.Width;
  wHeight := pngPNGImage.Height;
  pngPNGImage.Free;
end;
 
 
////////////////////////////////////////////////////////////////////////////////
procedure ReplaceRTFStringWithJPGOrPNGImage(strRTFFile, strImageFile, strStringToReplace : string);
{Convert a PNG or JPG to hex, combine the hex with RTF flags for an image and
 replace the desired string to be replaced with the whole image string.}
var
  fs                       : TFileStream;
  Buff : array [0..15] of byte;
  strImageHex, strImageInRTF, strRTFLine : string;
  CountRead : integer;
  HexText : array[0..31] of Char;
  strImgExtType : string;
  intImageWidthInTwips, intImageHeightInTwips : word;
  strlRTFTextFile : TStringList;
 
begin
  {Convert the image to hex (image format independent)}
  try
    {Open the image file into a file stream.}
    fs := TFileStream.Create(strImageFile, fmOpenRead or fmSharedenyNone);
    {Get the first line of the file stream.}
    CountRead := fs.Read(Buff, SizeOf(Buff));
    {Do the following until we are at the end of the buffer.}
    while CountRead <> 0 do
    begin
      {Convert the line of the stream to hex}
      BinToHex(Buff, HexText, CountRead);
      {Add the line of hex into the image hex string.}
      strImageHex := strImageHex + HexText + #13;
      {Get the next line of the buffer.}
      CountRead := fs.Read(Buff, SizeOf(Buff));
    end;
  finally
    {Free the file stream.}
    fs.Free;
  end;
 
  {Get the width and height of the image.  The handling will be
   different based on what type of image we are dealing with.}
  strImgExtType := AnsiUpperCase(ExtractFileExt(strImageFile));
 
  if (strImgExtType = '.JPG') then
  begin
    GetJPGDimensions(strImageFile, intImageWidthInTwips, intImageHeightInTwips);
    strImgExtType := '\jpegblip';
  end
  else if (strImgExtType = '.PNG') then
  begin
    GetPNGDimensions(strImageFile, intImageWidthInTwips, intImageHeightInTwips);
    strImgExtType := '\pngblip';
  end
  else
  begin
    MessageDlg('ReplaceRTFStringWithImage: Image format is not supported.', mtError, [mbOK], 0);
    exit;
  end;
 
  {Convert the width and height from pixels to twips: width or height / 96 (dpi) * 1440}
  intImageWidthInTwips := Round((intImageWidthInTwips / 96) * 1440);
  intImageHeightInTwips := Round((intImageHeightInTwips / 96) * 1440);
 
  {Construct the complete image string that will be seeded into the RTF.}
  strImageInRTF:= '{\pict{\*\picprop}' + strImgExtType +
                  '\picw' + IntToStr(intImageWidthInTwips) +
                  '\pich' + IntToStr(intImageHeightInTwips) + #13 +
                  strImageHex + '}';
 
  {Replace any text that matches the replacing string with the image string for
   the RTF.}
  try
    strlRTFTextFile := TStringList.Create;
    {Load the original RTF file}
    strlRTFTextFile.LoadFromFile(strRTFFile);
    {Put in a complete image string wherever the string to replace exists in the RTF file.}
    strlRTFTextFile.Text := StringReplace(strlRTFTextFile.Text, strStringToReplace, strImageInRTF, [rfreplaceAll]);
    {Save the changed RTF file.}
    strlRTFTextFile.SaveToFile(strRTFFile);
  finally
    strlRTFTextFile.Free;
  end;
end;


Edited by: Nathan Webers on Mar 4, 2016 9:31 AM
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02