Print Page | Close Window

Use of Delphi color constants?

Printed From: Debenu Quick PDF Library - PDF SDK Community Forum
Category: For Users of the Library
Forum Name: I need help - I can help
Forum Description: Problems and solutions while programming with the Debenu Quick PDF Library and Debenu PDF Viewer SDK
URL: http://www.quickpdf.org/forum/forum_posts.asp?TID=2278
Printed Date: 22 Nov 24 at 6:58PM
Software Version: Web Wiz Forums 11.01 - http://www.webwizforums.com


Topic: Use of Delphi color constants?
Posted By: greymont
Subject: Use of Delphi color constants?
Date Posted: 25 May 12 at 3:14PM
Has anyone dealt with converting the Delphi RGB color constants to the separate floating point values used by QuickPDF?

I'd like to use values like clWhite and clBlack and clRed in my program that creates PDF files but before I write the code that translates these into separate RGB values I thought I'd ask if anyone has done this before.




Replies:
Posted By: HNRSoftware
Date Posted: 27 May 12 at 2:05PM
I have not had any problems just doing the normal TColor to RGB byte conversions that I use in regular Delphi code and placing the byte values into the QPDF double variables.  I can dig out actual conversion code, but it is pretty trivial.


Posted By: HNRSoftware
Date Posted: 27 May 12 at 2:18PM
I may have given you bad advice - what I said is what my code appears to do, but the documentation for SetLineColor says "Sets the outline color for any subsequently drawn graphics. The values of the color parameters range from 0 to 1, with 0 indicating 0% and 1 indicating 100% of the color."which is pretty darned clear that a Red byte value of 127 should be used as  (127.0 / 255.0) or ~0.50 and so on.  I have no idea why my code says otherwise and I do not recall any problems using color.  Confused


Posted By: greymont
Date Posted: 28 May 12 at 10:45PM
Yeah, that's exactly the issue. QP uses 0.0-1.0 and everything else uses byte values of 0x0000 - 0xffff.

I can understand using the floating point values as percentages since it it totally platform and framework independent.  I do not understand why using the byte values works as you say it does.

If it were me I'd write the API so that:
1) if the value is 0.0 then it means no contribution, same as 0x0000.
2) if the floating point values were solely fractional 0.0 < value < 1.0 then interpret them as fractional as currently documented.
3) if the floating point value is > 1.0 (2.0 - 255.0) interpret the whole number part same as the byte values usually used, 0x0002 through 0xffff, or 2.0 - 255.0 and ignore any fractional part.
4) that leaves the value 1.0 which could be interpreted as 100% (as per choice 2 above) or 0x0001 (as per choice 3 above). My own choice would be to make 1.0 same as 0xffff and document it s if you really want 0x0001 then pass in 1.0001 or some other floating point value just above 1.0

Anyway, I just want to know what the intended usage is and whether pasing the byte values 0x0000-0xffff actually works. I guess I'll have to experiment some more. (I'm doing a lot of that with this product.)


Posted By: HNRSoftware
Date Posted: 28 May 12 at 11:38PM
The product is quite Delphi friendly.  I am doing a lot of experimenting with it, but the experiments almost always wind up with the code doing what it ought to, just not what my intuition thought.  One thing to keep in mind is that the orientation is multi-language, not just Delphi, so some of the conventions are not intuitive (to me).

I extend the TQuickPDF object and here is a piece of code I stuck in.

Procedure TQuickPDF.SetLineTColor(AColor : TColor);
var r,g,b : byte;
     begin
     TColorToRGB(AColor,r,g,b);
     self.SetLineColor(r,g,b);
     end;

this references a few of my library routines

Function  IntByte( int : integer; byt : byte = 0) : byte;
     begin  result := (int shr (byt * 8)) and $FF;  end;


Procedure TColorToRGB(c : TColor; var r,g,b :byte);
     begin
     r := intbyte(c,0);
     g := intbyte(c,1);
     b := intbyte(c,2);
     end;

Without writing a test program to prove it, I'm 99% sure the SetLineTColor does what it thinks it does.  I am happy to share my code, but it is literally millions of lines of code in units developed over 15-20 years (back to Turbo Pascal 1.0)

Now that I map my answer back to your question, I'm 99% sure my original thought was correct - just use the color bytes, not what the documentation implies as a number between 0 and 1.  Now I have to go back and test it...


Posted By: HNRSoftware
Date Posted: 28 May 12 at 11:46PM
yes, it does work the way I thought.  H


Posted By: greymont
Date Posted: 29 May 12 at 2:01AM
Well that is really curious. Makes me wonder what version of QP you are using.

I have the QP 8.15 source code and it clearly takes the 3 RGB values passed to SetLineColor and directly emits them to the PDF file using the RG command after limiting those values to 0.0 to 1.0. The PDF specification also clearly describes the RG command as accepting floating point values from 0.0 to 1.0, not values from 0 to 255.

So I cannot explain what you are seeing.

I am also enhancing the TQuickPDF class with convenience functions so thanks very much for sharing your added method. I think I will adapt it to convert the values to fractions and pass them on then test both strategies.

Curiouser and curiouser.


Posted By: HNRSoftware
Date Posted: 29 May 12 at 2:38AM
Well, that is fascinating - I'm also using 8.15 (Delphi 6 - I own higher versions but 6 is the one my fingers know).  I deleted debug logging lines from the code I put on the post, but activating it shows me that I am calling the SetLineColor function with the 3 rgb values (0-255) and I am seeing the colors I expect to see in the output pdf file.  Code completion shows me that I am typing into a non-overloaded function and it is expecting type double arguments.  I have not looked at the library source code - it is tough enough keeping track of my own - I just code lots of test programs and do logging wherever useful.  I have no idea what their code shows, but I'll bet the ranch that my code does it as I described.

 I guess I assumed that their code was smart enough to handle values 0.0000-0.9999 in one manner and  0-255 in another.  More likely, I never read the help page on the function and just assumed that rgb values were what I was always used to, and since it worked, I never looked back.

 You ought to be able to test your code with a couple of constant rgb s like 255 0 0

Send me your email and I will send you my MyQuickPDF.pas unit.  Because of all my longstanding support routines, you wouldn't be able to use it directly without me sending a lot more, but you might get some ideas from my code.  I would also like to view your approach if it is convenient for you.  I am Howard Richoux with address at h_richoux at yahoo.com.


Posted By: edvoigt
Date Posted: 29 May 12 at 4:55PM
Hi both,

I'm very sure, you are wrong about RGB-colorsetting in QPL. I did a small test to show why.

I wrote

QP.DrawText(0,0, 'before');
QP.SetTextColor(255, 127, 64);
QP.DrawText(0,0, 'after');


In case, that there would be anything converting it into 0..1 area, we had to find approx. 1.0 0.5 0.25 as values inside the PDF. For easier finding I made the both texts around.

But what is there:

BT               // begin text
1 0 0 1 0 0 Tm   // set text matrix
(before)Tj       // draw text
ET               // end text
1 1 1 rg         // set RGB-color
BT               // ...
1 0 0 1 0 0 Tm
(after)Tj
ET


You see there is no conversion, only a cut at 1.0, because values above would contradict the specification of PDF. So you should  for converting not spare the division by 255 to go from 0..255 to 0..1. There is no magic working for you.

Cheers

Werner



Posted By: HNRSoftware
Date Posted: 29 May 12 at 5:50PM
Hi Ed - you are absolutely right.  I had not looked closely at my colored output - really only used a few primary colors and they all looked fine because they were essentially all or nothing in the r/g/b department. I tried with some shades and they all disappeared.

So, this is my corrected code

Procedure TQuickPDF.SetLineTColor(AColor : TColor);
var r,g,b : byte;
     begin
     TColorToRGB(AColor,r,g,b);
     //no...self.SetLineColor(r,g,b);
     self.SetLineColor(r/255.0, g/255.0, b/255.0);
     end;
 

Once again, I have to remember to trust the docs.  Thanks - Howard


Posted By: greymont
Date Posted: 29 May 12 at 6:22PM
Yeah, I just finished a test program and found the same.

Now on to the other issues I have discovered.


Posted By: HNRSoftware
Date Posted: 29 May 12 at 6:24PM
Ed - do you have any notes on the output of the "PageContent" commands.  In decoding a complex file, I reverse-engineered the "m" as a moveto, "l"as a lineto, "c" as sort of a polygon. 
"S" showed up in a different file as a line segment.  The odd part is that all those pieces reconstruct almost all of the lines visible on the page, but a number of vertical lines are missing.  I am hypothesizing them as being related to some lines where "S" is the only thing on the line after s bunch of "m"s and "l"s. 

I hate to re-invent the wheel - there are not all that many different commands in the files I'm looking at -- text are the most complex -- haven't worked them through, but I hypothesize the text stuff as being delimited by lines of "BT" and "ET". 

It is not that I really NEED to know, but it is nagging at me.  Any clues or references you can give me would be appreciated.  Thanks - Howard




Posted By: greymont
Date Posted: 29 May 12 at 6:46PM
From the PDF specification for version 1.4:

TABLE 4.9   Path construction operators

x y m = Begin  a  new  subpath  by  moving  the  current  point  to  coordinates (x, y),  omitting  any  connecting  line  segment.  If  the  previous  path construction  operator  in  the  current  path  was  also  m,  the  new  m overrides it; no vestige of the previous m operation remains in the
path.

x   y l (lowercase L)  =     Append a straight line segment from the current point to the point (x, y). The new current point is (x, y).

x1 y1 x2 y2 x3 y3 c = Append a cubic Bézier curve to the current path. The curve extends
from  the  current  point  to  the  point  (x3, y3),  using  (x1, y1)  and(x2, y2) as the Bézier control points (see “Cubic Bézier Curves,” below). The new current point is (x3, y3).

x2 y2 x3 y3 v = Append a cubic Bézier curve to the current path. The curve extends
from the current point to the point (x3, y3), using the current point and (x2, y2) as the Bézier control points (see “Cubic Bézier Curves,” below). The new current point is (x3, y3).

x1 y1 x3 y3 y = Append a cubic Bézier curve to the current path. The curve extends
from  the  current  point  to  the  point  (x3, y3),  using  (x1, y1)  and (x3, y3) as the Bézier control points (see “Cubic Bézier Curves,” below). The new current point is (x3, y3).
 
h = Close  the  current  subpath  by  appending  a  straight  line  segment from  the  current  point  to  the  starting  point  of  the  subpath.  This operator  terminates  the  current  subpath;  appending  another  segment to the current path will begin a new subpath, even if the new
segment begins at the endpoint reached by the h operation. If the current subpath is already closed, h does nothing.


Looks like "h" operator also results in a line to the originating point. Maybe that's what creates the vertical lines.


Posted By: HNRSoftware
Date Posted: 29 May 12 at 7:22PM
Hi Doug - thanks - I will study that and go track down some  "cubic Bézier curve" code, but that all makes sense.

So, this stuff is really pdf internal coding? not something of QPL's?

H


Posted By: greymont
Date Posted: 29 May 12 at 7:34PM
I have not yet seen any PDF content generated by QP that does not look like normal PDF "commands". I think it is possible to define something like a "macro" command and then use it in a PDF but I'm not 100% sure about that and have not seen it yet.


Posted By: HNRSoftware
Date Posted: 29 May 12 at 10:53PM
Thanks both - I googled a pdf reference and the chapter on graphics suddenly makes great sense.  I don't think I would have grasped it without your info and the trial and error work.  ABSOLUTELY FASCINATING.

I haven't answered my all questions yet, but, all of a sudden, they look very answerable.  I need to clean up a bit of confused logic regarding graphics object processing, but then it is off to the races.  Parsing and executing the commands is both easier and much more complex than I would have thought.  Fortunately I only have to deal with a subset of the nearly infinite ways those commands could be combined.

Thanks - Howard


Posted By: edvoigt
Date Posted: 30 May 12 at 10:43AM
Hi,

there are a lot of things needed really to understand how a PDF is to be interpreted by any reader. It's a full time job. An easy entry to understand a first part is a look into appendix A (operator summery). But it is only a first step. Not only operators are working for us.

If you use QPL-(drawing-)commands and look in the resulting PDF, so you understand better, what QPL is doing for you and you get step by step ground under your feets.

Cheers,

Werner


Posted By: HNRSoftware
Date Posted: 30 May 12 at 10:50AM
Hi Werner - thanks - that is exactly what I started doing.  It occurred to me that QPL was probably oriented to generating those commands, so the call structure should be very parallel to what I was seeing -- if I saw something in the command list, there was probably a call to generate it.

This whole rendering exploration is far beyond what I need to do, but it just seems so interesting, and I had most of the tools sitting in front of me.  Life keeps getting more interesting....  Thanks - Howard



Print Page | Close Window

Forum Software by Web Wiz Forums® version 11.01 - http://www.webwizforums.com
Copyright ©2001-2014 Web Wiz Ltd. - http://www.webwiz.co.uk