You are not logged in.
I'm trying my hand again at the clipping problem when printing a bitmap in GDI+ with clipping.
Here are two images. One is from the the generated EMF and the other from the PDF generated with the latest mormot2.
It seems that clipping in PDF is only restricted to a box, and not to a complete non-square region.
Is this true?
Or is clipping even supported for EnumEMFFunc() for GDI+?
Seeing that ClipRgn and MetaRgn are TPdfBox it seems that it couldn't even do a region but only a box.
If it should be supported then I can investigate further why it doesn't work correctly.
(otherwise I would be wasting a lot of time )
EMF
PDF
Last edited by rvk (2023-09-07 11:04:06)
Offline
Hmmmm, Yeah, definitely not supported.
Size of region data from GDI is 208 bytes.
EMR_EXTSELECTCLIPRGN:
begin
dum1 := PEMRExtSelectClipRgn(R)^.cbRgnData; // <---- has a block of 208 bytes
E.ExtSelectClipRgn(@PEMRExtSelectClipRgn(R)^.RgnData[0],
PEMRExtSelectClipRgn(R)^.iMode);
end;
But the function ExtSelectClipRgn() doesn't seem to do much with the data parameter??
procedure TPdfEnum.ExtSelectClipRgn(data: PRgnDataHeader; iMode: DWord);
begin
try
with DC[nDC] do
case iMode of
RGN_COPY:
begin
ClipRgn := MetaRgn; // where is the data parameter used??
ClipRgnNull := false;
end;
end;
except
on e: Exception do
; // ignore any error (continue EMF enumeration)
end;
end;
Any ideas?
Was this meant to be functional or is it still in development?
Did this work in the past ???
Seeing this post: https://synopse.info/forum/viewtopic.ph … 071#p20071
Edit:
The code from that old topic (which was once in SynPDF) seems to be working much better. (no anti-alias but that might be fixed.)
Why was that code removed?
Last edited by rvk (2023-09-07 11:54:32)
Offline
Clipping is not supported yet in our PDF engine.
This code was removed because it introduced regression to a lot of users already using the library.
It is sadly an usual pattern: to please some specific conditions for 1% of the users, it breaks 50% of the others.
If clipping is to be supported, it should be properly.
Online
I couldn't find that many problems with the old code on the forum.
No problem... I added the old code back with the addition of checking for data^.iMode is RGN_COPY in the ExtSelectClipRgn (which was mentioned in that topic).
// we are handling RGN_COPY (5) only..
if data^.iMode <> RGN_COPY then exit;
For me that works for now. If there are any problems I will mention them here.
Offline
The code is almost identical with the old code (with the check for iMode added).
But I will test this some more (we wouldn't want a bad patch ) and create a pull request with patch (once I know how to do that )
Offline
You can send a pull request with your patched code, I could make a look at it, and probably merge it.
BTW. Do you have some reference (link, documentation or description) for the problems many of those users had with the old clipping code?
(So I could test this and see if there is an alternative fix is this still exists in current code.)
Offline
Grrr. translating these coordinates is really hard.
Still not perfect.
It's also not just adding or substracting a value because the ratio/proportions are also off when using BoxI().
I can't figure out what other translation then BoxI() should be done.
The larger the image, the more deviation.
(There is also a big bug in PDF Engine when dealing with bitmaps of size 7x7 (very small). It crashes, even without the clipping stuff.)
Last edited by rvk (2023-09-08 14:57:03)
Offline
YES, PERFECT. I think I found a problem in the drawing of the DrawBitmap() in the PDF Engine.
For the old ExtSelectClipRgn code there was a correction of bottom (and I added right) of +1.
This was because in BoxI() there is I2Y(Rect.Bottom - 1) and I2X(Rect.Right - 1) in the correction to coordinates and size.
For the correct handling you would also need to do the Bottom + 1 and Right + 1 in the DrawBitmap() (same as in ExtSelectClipRgn).
So the bitmap is now drawn always 1 bitmap pixel too small (???).
Can you comment on why the BoxI() has the - 1 for Bottom and Right ??
There might be other places where this is a problem and because this is outside of the clipping problem I thought you might have some comments.
I can correct those before calling BoxI() in DrawBitmap() and ExtSelectClipRgn() and the outcome is perfect now:
R := TRect(Rect(xd, yd, wd + xd, hd + yd));
NormalizeRect(R);
Inc(R.Bottom); // <----- these 2 lines
Inc(R.Right); // <----- these 2 lines
box := BoxI(R, true);
clp := GetClipRect;
if (clp.Width > 0) and
(clp.Height > 0) then
Doc.CreateOrGetImage(bmp, @box, @clp) // use cliping
else
Doc.CreateOrGetImage(bmp, @box, nil);
// Doc.CreateOrGetImage() will reuse any matching TPdfImage
// don't send bmi and bits parameters here, because of StretchDIBits above
And this now seems pixel perfect with the EMF Explorer (which is this one):
Last edited by rvk (2023-09-08 15:28:28)
Offline
Ok, here is another proof that the bitmap was drawn too small.
I added a FillRectangle of 1x1 at coordinates 0,0 1,1 and 4,6.
You see clearly that in the original drawing of bitmap with 2x4 pixels (drawn at 2,2), the lower right is not connected to the FillRectangle.
So, or all the BoxI() for FillRect etc. is not correct (but they seems to be places correctly) or the code for DrawBitmap is incorrect (too small).
After some further testing I will prepare a pull request for the ExtSelectClipRgn with the addition of corrected bottom/right in DrawBitmap.
(After that, when I get the time I'll see if I can tackle the EMR_SELECTCLIPPATH, which is completely missing now).
When corrected:
Offline
I searched back to where these changes were reverted.
Here are some references (for documentation and futures sake).
Original commit in SynPDF and mORMot was on 2015-11-09
https://github.com/synopse/SynPDF/commi … 55924c4d9c
https://github.com/synopse/mORMot/commi … b4077dc725
The revert in mORMot was done here on 2017-01-13 (and SynPdf on 2017-01-18):
https://github.com/synopse/mORMot/commi … 215790822e
https://github.com/synopse/SynPDF/commi … 8388dc689a
It points to this topic: https://synopse.info/forum/viewtopic.php?pid=22968
The strange thing is that this is discussed earlier (in 2016) but then this change wouldn't have happened yet.
https://synopse.info/forum/viewtopic.ph … 071#p20071
On the commit on SynPDF there are some comments in 2022 where it's mentioned the code was good (but was never followed upon):
https://github.com/synopse/SynPDF/commi … a#comments
https://github.com/synopse/SynPDF/commi … #r84370305
I've created a pull request (my first ) with the changes (including the check on iMode = 5).
I also fixed the DrawBitmap() to add 1 for Bottom and Right (the bitmap was actually drawn too small).
"Reintroduce SelectClipRgn support for GDI+ and fix DrawBitmap()"
Hopefully nobody has problems with it (otherwise I'm willing to help, with a problem .emf, to find the problem).
Offline
I have merged (and slightly refactored) your pull request.
https://github.com/synopse/mORMot2/pull/221
Thanks a lot for sharing!
Online
Thanks for the merge.
When looking for the word "clipping" here on the forum I came across this topic from MtwStark.
https://synopse.info/forum/viewtopic.php?id=4276
It seems (s)he made a lot (and I mean A LOT) of changes to SynPDF regarding the clipping-code.
I couldn't find a pull request (or even fixes on github).
I understand that those changes were a LOT to just merge with the existing code (and it wasn't even as fix for mORMot2) and was left behind because of this.
If I have any other fixes I'll try to keep them small and clearly understandable
Offline
When looking for the word "clipping" here on the forum I came across this topic from MtwStark.
I don't know if my hint is helpful. I haven't used SynPDF yet and only skimmed the thread, but when I hear the word "clipping" I immediately think of Angus Johnson Clipper2 library, which is also used with Image32. The older Clipper1 library can be found here.
With best regards
Thomas
Offline
Unfortunately, this commit introduces a new problem as described in that thread: https://synopse.info/forum/viewtopic.php?pid=41447
It includes a screenshot of the problem as well as a sample application to reproduce this.
Offline