Page 1 of 1

OnHTMLSaveImage or OnSaveImage2

Posted: Thu Nov 30, 2006 10:27 pm
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

Posted: Fri Dec 01, 2006 9:48 pm
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.

Posted: Fri Dec 01, 2006 10:16 pm
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

Posted: Sat Dec 02, 2006 12:32 pm
by Sergey Tkachenko
Please give me example showing that OnSaveImage2 is not called for some images.

Posted: Sat Dec 02, 2006 2:05 pm
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

Posted: Sun Dec 03, 2006 8:22 pm
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).

Posted: Sun Dec 17, 2006 3:34 pm
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

Posted: Mon Dec 18, 2006 11:58 am
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)

Posted: Mon Dec 18, 2006 12:24 pm
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

Posted: Sat Dec 23, 2006 3:47 pm
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.