OnHTMLSaveImage or OnSaveImage2

General TRichView support forum. Please post your questions here
Post Reply
krho
Posts: 33
Joined: Wed Nov 01, 2006 10:17 am

OnHTMLSaveImage or OnSaveImage2

Post by krho »

Hm.
Here is the thing I don't understand. Reading forum and documentation it seems that when saving document to HTML I can either use OnHTMLSaveImage or OnSaveImage2 event, but as it came to me is, that sometimes the OnSaveImage2 is not called at all, only OnHTMLSaveImage event is called.

So why do I have to mess with two events.

BTW: I believe that in rvhtmlimporter function ReadImage, line 1516 should be FileName := GetFullFileName(Trim(src));, because sometimes param src comes with beginning or ending spaces, which are "leftover" from parser.

Regards,
Miha
Sergey Tkachenko
Site Admin
Posts: 17606
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

The difference between these two events how the image is specified.

In OnHTMLSaveImage, it is defined by RVData and ItemNo parameters. I.e., only the item containing image is specified (or some special cases when ItemNo=-1), you need to extract the image yourself. You need to write code extracting image from all possible sources (richview background, cell background, table background, picture, hot-picture, "bullet", "hotspot", list maker)

OnSaveImage2 is simpler - the image is defined by Graphic parameter. The only problem with this event is related to pictures from image list ("bullets", "hotspots", some list markers). You cannot save them with transparency, because they are passed to this event as TBitmap.
krho
Posts: 33
Joined: Wed Nov 01, 2006 10:17 am

Post by krho »

Yeah, but still. OnSaveImage2 is NOT called always, so I have to write messy code with two events and I'll probably end with more images than necessary (duplicates)?
All I need is to get all images preferably with with file names, and cid:imgX written instead image, well and saving image as png if it's of a TBitmap type.

I'm using richview actions. Code I'm using is below.

Code: Select all

procedure TfrmComposeEditorRichView.TntFormCreate(Sender: TObject);
begin
  txtMessage.Align := alClient;
  Clear;

  rvActionInsertPicture1.StoreFileName := True;
  RV_RegisterHTMLGraphicFormat(TPNGObject);
  RV_RegisterHTMLGraphicFormat(TJvGIFImage);
end;

procedure TfrmComposeEditorRichView.txtMessageSaveImage2(
  Sender: TCustomRichView; Graphic: TGraphic; SaveFormat: TRVSaveFormat;
  const Path, ImagePrefix: string; var ImageSaveNo: Integer;
  var Location: string; var DoDefault: Boolean);

var bmp: TBitmap;
var png: TPNGObject;
var strm: TTntFileStream;
var fn: WideString;
begin
  DoDefault := False;
  png := nil;

  //save non png, gif, jpg as png
  if not ((Graphic is TJPEGImage) or (Graphic is TPNGObject) or
     (Graphic is TJvGIFImage)) then begin

    bmp := TBitmap.Create;
    try
      bmp.Assign(Graphic);
    except
      bmp.Width := Graphic.Width;
      bmp.Height := Graphic.Height;
      bmp.Canvas.Draw(0, 0, Graphic);
    end;

    png := TPNGObject.CreateBlank(COLOR_RGB, 8, Graphic.Width, Graphic.Height);
    png.InterlaceMethod := imNone;
    png.CompressionLevel := 9;
    png.Assign(bmp);
    FreeAndNil(bmp);
  end;

  //get file name
  if png <> nil then
    fn := WideGetUniqueFileName(Path + tmpFilePrefix + ImagePrefix, '.' + GraphicExtension(TGraphicClass(png.ClassType)))
  else
    fn := WideGetUniqueFileName(Path + tmpFilePrefix + ImagePrefix, '.' + GraphicExtension(TGraphicClass(Graphic.ClassType)));

  images.Add(fn);

  strm := TTntFileStream.Create(fn, fmCreate or fmOpenReadWrite or fmShareExclusive);
  if png <> nil then
    png.SaveToStream(strm)
  else
    Graphic.SaveToStream(strm);

  FreeAndNil(strm);
  FreeAndNil(png);

  fn := WideExtractFileName(fn);
  fn := RightStr(fn, Length(fn) - Length(tmpFilePrefix));
  Location := 'cid:' + fn;
end;

//and next line to export to html
    txtMessage.SaveHTMLToStreamEx(ms, df.Temp, _('si.Mail composed message'), 'siMailImage',
      '', '', '', [rvsoUseItemImageFileNames, rvsoUseCheckpointsNames, rvsoUTF8]);
Regards,
Miha
Sergey Tkachenko
Site Admin
Posts: 17606
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Please give me example showing that OnSaveImage2 is not called for some images.
krho
Posts: 33
Joined: Wed Nov 01, 2006 10:17 am

Post by krho »

It ws not called for images that existed on harddrive, I was using rvsoUseItemImageFileNames when exporting to html, nonetheless even throug I have set rvActionInsertPicture1.StoreFileName := True; it seems that file name is not saved with action and that's why I didn't catch this sooner. And this is probably why

BTW any chances of getting full (full not relative) image file name in Location variable by default if it is present?
Something like OnSaveHtmlSaveImage2 with parameters from OnHtmlSaveImage and OnSaveImage2 combined.
In that case and with location filled with current image file name it would be possible to. Save "duplicate" images only once. Re-save images.

edit: Or maybe I'm talking rubbish and I can do everthing with OnHtmlSaveImage. /me is going to read some documentation.

Regards,
Miha
Sergey Tkachenko
Site Admin
Posts: 17606
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Well, you are right.
OnHTMLSaveImage is called before checking rvsoUseItemImageFileNames. It allows to override all image saving behavior, including rvsoUseItemImageFileNames option.

OnSaveImage2 is called only if TRichView decides that the image must be saved. It's natural that it is not called for images with defined file names when rvsoUseItemImageFileNames is included in saving Options (will be mentioned in the help file)

As for TrvActionInsertPicture... It stores image file name not in the property that is used for saving picture to HTML, but in the item name. Will be fixed (as an option) in the next update.

As for the initial value of Location parameter, yes, it is a relative path.
In OnHTMLSaveImage event you can get the original path as RVData.GetItemExtraStrProperty(ItemNo, rvespImageFileName, s).
krho
Posts: 33
Joined: Wed Nov 01, 2006 10:17 am

Post by krho »

RVData.GetItemExtraStrProperty(ItemNo, rvespImageFileName, s).
But this doesn't work for background image :( Where ItemNo is negative number e.g -1. And the same probably applies for table/table cell background images.

So how to get file name for background image?

Regards,
Miha
Sergey Tkachenko
Site Admin
Posts: 17606
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Cells have BackgroundImageFileName property, it is used like rvespImageFileName extra property of items.
So the only problem is with TRichView.BackgroundBitmap. This is one image, and you can store its file name yourself (if it needs to be saved with document, use DocProperties)
krho
Posts: 33
Joined: Wed Nov 01, 2006 10:17 am

Post by krho »

The "problem" with above resolution is that I have patch sources for rvactions and rvhtml import, otherwise I haven't done anything.

BTW, how do I get TGraphic in OnHTMLSaveImage, so I can save images without file name myself.
If I set DoDefault to True with that images are saved by trichview. I tought that OnSaveImage2 will be called.

FileName property in BackgroundBitmap would be most welcome.

Regards,
Miha
Sergey Tkachenko
Site Admin
Posts: 17606
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Ok, in the next update of RichViewActions, TrvActionBackground will have new event and property:
1) OnChange event - occurs after clicking "OK" in the dialog
2) ImageFileName: String - background image file name.

You can use this event and property to store file name for background image somewhere.
Post Reply