Graphics to PDF

P

Proposal Doctor

I am interested in knowing which graphics format works best in Access 2007
when the destination is PDF. I have tried gif, jpeg, and tiff. And I have
tried copying a graphic directly from PowerPoint into an Access Report, which
works best.

Does anyone have a better solution? My problem is with an oval. It is
jagged. Text looks great.

Also, what is the difference between using "Image" and using "Logo?"

Thanks.

David
 
A

Arvin Meyer [MVP]

Proposal Doctor said:
I am interested in knowing which graphics format works best in Access 2007
when the destination is PDF. I have tried gif, jpeg, and tiff. And I
have
tried copying a graphic directly from PowerPoint into an Access Report,
which
works best.

Does anyone have a better solution? My problem is with an oval. It is
jagged. Text looks great.

Vector files do not leave jagged edges. Try using a WMF format
Also, what is the difference between using "Image" and using "Logo?"

An image is any image, a logo is an image that's a symbol for a corporate
entity.
 
J

James A. Fortune

I am interested in knowing which graphics format works best in Access 2007
when the destination is PDF. I have tried gif, jpeg, and tiff. And I have
tried copying a graphic directly from PowerPoint into an Access Report, which
works best.

Does anyone have a better solution? My problem is with an oval. It is
jagged. Text looks great.

For those creating PDF files directly from Access or from a PDF
creation tool (i.e., without using the A2K7 PDF Add-In), perhaps the
following solution for a vector ellipse will work until I come up with
something better.

Objective: Draw an ellipse centered at (X, Y) pts with eccentricity e
used to stretch a circle along the X-Axis using the existing brush
color, or (R,G,B) values if they are specified.

Although stretching out a circle is simpler than creating an ellipse
from scratch, it has a disadvantage that the width of the line also
stretches, making the boundary tenuous near the minor axis. That
might look O.K. for smaller ellipses or ones having only a slight
eccentricity (1 = perfectly round). I checked that the center of the
circle did not change when stretching by marking the center of the
original circle after the ellipse was created and the graphics
environment restored, but I didn't actually measure it on the printed
page, so it's possible that the origin moves when the circle is
stretched.

'Begin module code
Public Function DrawFlatEllipse(ByVal dblEccentricity As Double, ByVal
dblX As Double, ByVal dblY As Double, ByVal dblR As Double, ByVal
dblLineWidth As Double, Optional dblRed As Double = -1, Optional
dblGreen As Double, Optional dblBlue As Double) As String
Dim P1x As Double
Dim P1y As Double
Dim P1ux As Double
Dim P1uy As Double
Dim P1dx As Double
Dim P1dy As Double
Dim P2x As Double
Dim P2y As Double
Dim P2rx As Double
Dim P2ry As Double
Dim P2lx As Double
Dim P2ly As Double
Dim P3x As Double
Dim P3y As Double
Dim P3ux As Double
Dim P3uy As Double
Dim P3dx As Double
Dim P3dy As Double
Dim P4x As Double
Dim P4y As Double
Dim P4rx As Double
Dim P4ry As Double
Dim P4lx As Double
Dim P4ly As Double
Dim strTemp As String
Dim strCR As String

strCR = Chr(13)
P1x = dblX + dblR
P1y = dblY
P1ux = P1x
P1uy = P1y + CRatio * dblR
P1dx = P1x
P1dy = P1y - CRatio * dblR
P2x = dblX
P2y = dblY + dblR
P2rx = P2x + CRatio * dblR
P2ry = P2y
P2lx = P2x - CRatio * dblR
P2ly = P2y
P3x = dblX - dblR
P3y = dblY
P3ux = P3x
P3uy = P3y + CRatio * dblR
P3dx = P3x
P3dy = P3y - CRatio * dblR
P4x = dblX
P4y = dblY - dblR
P4rx = P4x + CRatio * dblR
P4ry = P4y
P4lx = P4x - CRatio * dblR
P4ly = P4y
strTemp = "q" & strCR
strTemp = strTemp & CStr(dblLineWidth) & " w" & strCR
If dblRed <> -1 Then
strTemp = strTemp & CStr(dblRed) & " " & CStr(dblGreen) & " " & CStr
(dblBlue) & " rg" & strCR
End If
'Set a new graphics origin at P4x, P3y
strTemp = strTemp & "1 0 0 1 " & CStr(P4x) & " " & CStr(P3y) & " cm" &
strCR
'Change the scale in the x direction, use dblEccentricity
strTemp = strTemp & CStr(Round(1 / dblEccentricity, 4)) & " 0 0 1 0 0
cm" & strCR
'Move to the right side of the circle
strTemp = strTemp & CStr(P1x - P4x) & " " & CStr(P1y - P3y) & " m" &
strCR
strTemp = strTemp & CStr(P1ux - P4x) & " " & CStr(P1uy - P3y) & " " &
CStr(P2rx - P4x) & " " & CStr(P2ry - P3y) & " " & CStr(P2x - P4x) & "
" & CStr(P2y - P3y) & " c" & strCR
strTemp = strTemp & CStr(P2lx - P4x) & " " & CStr(P2ly - P3y) & " " &
CStr(P3ux - P4x) & " " & CStr(P3uy - P3y) & " " & CStr(P3x - P4x) & "
" & CStr(P3y - P3y) & " c" & strCR
strTemp = strTemp & CStr(P3dx - P4x) & " " & CStr(P3dy - P3y) & " " &
CStr(P4lx - P4x) & " " & CStr(P4ly - P3y) & " " & CStr(P4x - P4x) & "
" & CStr(P4y - P3y) & " c" & strCR
strTemp = strTemp & CStr(P4rx - P4x) & " " & CStr(P4ry - P3y) & " " &
CStr(P1dx - P4x) & " " & CStr(P1dy - P3y) & " " & CStr(P1x - P4x) & "
" & CStr(P1y - P3y) & " c" & strCR
strTemp = strTemp & "S" & strCR
strTemp = strTemp & "Q" & strCR
DrawFlatEllipse = strTemp
End Function
'End module code

How I made the layout for importation into the PDFLayoutViewer
database:

'Begin code behind form
Private Sub cmdMakeFlatEllipse_Click()
Dim strOut As String
Dim strFileOut As String

strFileOut = "C:\FlatEllipseLayout.txt"
strOut = DrawFlatEllipse(0.5, 200, 350, 50, 1.35, 0.7, 0.3, 0.5)
Open strFileOut For Output As #1
Print #1, strOut
Close
MsgBox ("Done.")
End Sub
'End code behind form

A sample output PDF file (produced from A97) is available at:

https://files.oakland.edu/users/fortune/web/FlatEllipse.pdf

I used the Landscape option that I recently added to my
PDFLayoutViewer database. The vector based curves look good even at a
6400% PDF zoom level. Perhaps I can come up with something better in
time. The fact that Bezier curves must be used to create ellipses
having constant line widths in PDF documents complicates their
creation. To create a circle using Bezier curves, I used a technique
found at:

http://www.tinaja.com

James A. Fortune
(e-mail address removed)

Disclaimer: Any programming examples shown are for illustration
purposes only, without warranty either expressed or implied. This
includes, but is not limited to, the implied warranties of
merchantability or fitness for a particular purpose. This post assumes
that you are familiar with the programming language that is being
demonstrated and with the tools that are used to create and to debug
procedures. I might explain the functionality of a particular
procedure, but I am under no obligation to modify these examples to
provide added functionality or to construct procedures to meet your
specific requirements. Any code samples posted contain no known
hidden material defects. However, anyone who uses any code sample
posted does so with the understanding that they are responsible for
any testing of any illustrative code sample for any particular use.
Furthermore, anyone using an illustrative code sample I provide or
code derived from it does so at their own risk.
 
J

James A. Fortune

For those creating PDF files directly from Access or from a PDF
creation tool (i.e., without using the A2K7 PDF Add-In), perhaps the
following solution for a vector ellipse will work until I come up with
something better.

Here is a sample of a PDF ellipse created from A97 using about 28
Bezier curves.

https://files.oakland.edu/users/fortune/web/TrueEllipse.pdf

It should be possible to apply a coordinate transformation in order to
tilt the ellipse any amount and still have it be fairly smooth.

James A. Fortune
(e-mail address removed)
 
J

James A. Fortune

Objective: Draw an ellipse centered at (X, Y) pts with eccentricity e
used to stretch a circle along the X-Axis using the existing brush
color, or (R,G,B) values if they are specified.

Although stretching out a circle is simpler than creating an ellipse
from scratch, it has a disadvantage that the width of the line also
stretches, making the boundary tenuous near the minor axis. That
might look O.K. for smaller ellipses or ones having only a slight
eccentricity (1 = perfectly round). I checked that the center of the
circle did not change when stretching by marking the center of the
original circle after the ellipse was created and the graphics
environment restored, but I didn't actually measure it on the printed
page, so it's possible that the origin moves when the circle is
stretched.

I worked some more on getting the PDF ellipses smoother, plus I'm
including the code I used to create the layout as input to the
PDFLayoutViewer (modified with a Landscape option):

https://files.oakland.edu/users/fortune/web/TrueEllipse2.pdf

Note that I specify the lengths of the major and minor axes instead of
using the eccentricity. It wouldn't be difficult to free the delta
angle from its current limitations.

'Code behind form
Dim strOut As String
Dim strFileOut As String
Dim strCR As String

strCR = Chr(13)

strFileOut = "C:\TrueEllipseLayout.txt"
'Mark the center of the ellipse with a crosshair
strOut = "0.3 w" & strCR
strOut = strOut & "195 500 m" & strCR
strOut = strOut & "205 500 l" & strCR
strOut = strOut & "200 495 m" & strCR
strOut = strOut & "200 505 l" & strCR
strOut = strOut & "S" & strCR
strOut = strOut & DrawTrueEllipse(200, 500, 30, 80, 50, 0, 0, 0.42353)
Open strFileOut For Output As #1
Print #1, strOut
Close
MsgBox ("Done.")
'End Code behind form

'Begin Module Code

Public Type Curve
DX As Double
DY As Double
L1 As Double
Alpha As Double
L4 As Double
Beta As Double
End Type

Public Type PiecewiseCurve
Curves(300) As Curve
End Type

Public Function DrawTrueEllipse(dblX As Double, dblY As Double, N As
Integer, dblA As Double, dblB As Double, Optional dblR As Double = -1,
Optional dblG As Double, Optional dblBlue As Double) As String
Dim strTemp As String
Dim strCR As String
Dim thePiecewiseCurve As PiecewiseCurve
Dim I As Integer
Dim DeltaTheta As Integer
Dim Theta As Integer
Dim dblCurX As Double
Dim dblCurY As Double
Dim X1 As Double
Dim X2 As Double
Dim Y1 As Double
Dim Y2 As Double
Dim NSeg As Integer
Dim boolSuccess As Boolean
Dim dblRefAngle As Double
Const DegToRad = 0.0174532925

'dblA = Half the major axis in pts.
'dblB = Half the minor axis in pts.

'For now use N's that go into 360 evenly
DeltaTheta = 360 / N
NSeg = 0
dblCurX = 0
dblCurY = 0
X1 = 0
Y1 = 0
X2 = 0
Y2 = 0
For Theta = 0 To (360 - DeltaTheta) Step DeltaTheta
NSeg = NSeg + 1
X1 = X2
Y1 = Y2
boolSuccess = GetXY(dblA, dblB, CDbl(Theta + DeltaTheta), dblCurX,
dblCurY)
X2 = dblCurX
Y2 = dblCurY
dblRefAngle = GetReferenceAngle(CDbl(Theta + DeltaTheta), dblCurX,
dblCurY, dblA, dblB)
thePiecewiseCurve.Curves(NSeg).Beta = GetBezierAngle(CDbl(Theta +
DeltaTheta), dblRefAngle, "Beta")
If NSeg = 1 Then 'No previous computation
boolSuccess = GetXY(dblA, dblB, CDbl(Theta), dblCurX, dblCurY)
X1 = dblCurX
Y1 = dblCurY
dblRefAngle = GetReferenceAngle(CDbl(Theta), dblCurX, dblCurY,
dblA, dblB)
thePiecewiseCurve.Curves(NSeg).Alpha = 90
Else
thePiecewiseCurve.Curves(NSeg).Alpha = thePiecewiseCurve.Curves
(NSeg - 1).Beta
'Use the X2, Y2 values from the previous loop for X1, Y1
End If
thePiecewiseCurve.Curves(NSeg).DX = X2 - X1
thePiecewiseCurve.Curves(NSeg).DY = Y2 - Y1
thePiecewiseCurve.Curves(NSeg).L1 = 10 * dblA * Sin(DeltaTheta *
DegToRad) / N
thePiecewiseCurve.Curves(NSeg).L4 = 10 * dblA * Sin(DeltaTheta *
DegToRad) / N
Next Theta
'Start at the right edge of the ellipse
strTemp = DrawPiecewiseCurve(dblX + dblA, dblY, 0.2,
thePiecewiseCurve, NSeg, dblR, dblG, dblBlue, False)
DrawTrueEllipse = strTemp
End Function

Public Function DrawPiecewiseCurve(dblX As Double, dblY As Double,
dblThickness As Double, thePiecewiseCurve As PiecewiseCurve, N As
Integer, Optional dblR As Double = -1, Optional dblG, Optional dblB,
Optional boolFill As Boolean = False) As String
Dim I As Integer
Dim J As Integer
Dim strTemp As String
Dim strCR As String
Dim X2 As String
Dim Y2 As String
Dim X3 As String
Dim Y3 As String
Dim X4 As String
Dim Y4 As String
Dim X As Double
Dim Y As Double
Dim dblSumX As Double
Dim dblSumY As Double
Const DegToRad = 0.0174532925

strCR = Chr(13)
strTemp = "%PiecewiseCurve" & strCR
strTemp = strTemp & "q" & strCR
strTemp = strTemp & CStr(dblThickness) & " w" & strCR
If dblR <> -1 Then
strTemp = strTemp & CStr(dblR) & " " & CStr(dblG) & " " & CStr(dblB)
& " RG" & strCR
End If
strTemp = strTemp & CStr(dblX) & " " & CStr(dblY) & " m" & strCR
X = dblX
Y = dblY
For I = 1 To N
With thePiecewiseCurve.Curves(I)
'Calculate coordinates of P2 and P3
X4 = CStr(X + .DX)
Y4 = CStr(Y + .DY)
X2 = CStr(X + .L1 * Cos(.Alpha * DegToRad))
Y2 = CStr(Y + .L1 * Sin(.Alpha * DegToRad))
X3 = CStr(X4 - .L4 * Cos(.Beta * DegToRad))
Y3 = CStr(Y4 - .L4 * Sin(.Beta * DegToRad))
X = X + .DX
Y = Y + .DY
strTemp = strTemp & X2 & " " & Y2 & " " & X3 & " " & Y3 & " " &
CStr(X4) & " " & CStr(Y4) & " c" & strCR
End With
Next I
If boolFill = True Then
If dblR <> -1 Then
strTemp = strTemp & CStr(dblR) & " " & CStr(dblG) & " " & CStr
(dblB) & " rg" & strCR
End If
strTemp = strTemp & "b" & strCR
End If
strTemp = strTemp & "S" & strCR
strTemp = strTemp & "Q" & strCR
DrawPiecewiseCurve = strTemp
End Function
'End Module Code

Once a reasonable number of arcs is chosen, the main technique for
smoothing out the ellipse is to adjust the parameters L1 and L4, which
correspond to the distance of the Bezier control points from their
respective origin. Lengthening or shortening those distances seem to
tighten or loosen the control point's "draw" on the Bezier Curve. Too
much of either is not good. You can end up with "corners" along your
ellipse or "loops" if the lengths become too short or too long. I
stopped when I got the ellipse substantially smooth, but could have
gotten it smoother with more effort. Besides, at 0.2 line width it's
pretty easy to catch major flaws. It turns out I needed to be able to
create filled ellipses anyway in order to make a vector version of the
company's new logo to put on PDF reports.

James A. Fortune
(e-mail address removed)

Disclaimer: Any programming examples shown are for illustration
purposes only, without warranty either expressed or implied. This
includes, but is not limited to, the implied warranties of
merchantability or fitness for a particular purpose. This post assumes
that you are familiar with the programming language that is being
demonstrated and with the tools that are used to create and to debug
procedures. I might explain the functionality of a particular
procedure, but I am under no obligation to modify these examples to
provide added functionality or to construct procedures to meet your
specific requirements. Any code samples posted contain no known
hidden material defects. However, anyone who uses any code sample
posted does so with the understanding that they are responsible for
any testing of any illustrative code sample for any particular use.
Furthermore, anyone using an illustrative code sample I provide or
code derived from it does so at their own risk.
 
J

James A. Fortune

boolSuccess = GetXY(dblA, dblB, CDbl(Theta + DeltaTheta), dblCurX,
dblCurY)
X2 = dblCurX
Y2 = dblCurY
dblRefAngle = GetReferenceAngle(CDbl(Theta + DeltaTheta), dblCurX,
dblCurY, dblA, dblB)
thePiecewiseCurve.Curves(NSeg).Beta = GetBezierAngle(CDbl(Theta +
DeltaTheta), dblRefAngle, "Beta")

It would probably be nice to show code for the following also:

GetXY()
GetReferenceAngle()
GetBezierAngle()

Public Function GetXY(dblA As Double, dblB As Double, dblTheta As
Double, ByRef dblX As Double, ByRef dblY As Double) As Boolean
Dim dblDenom As Double
Dim dblAbsX As Double
Dim dblAbsY As Double
Const DegToRad = 0.0174532925

GetXY = True
If dblTheta = -90 Or dblTheta = 90 Then
dblX = 0
dblY = Sgn(dblTheta) * dblB
Exit Function
End If
If dblTheta = 0 Then
dblX = dblA
dblY = 0
Exit Function
End If
If dblTheta = 180 Then
dblX = -dblA
dblY = 0
Exit Function
End If
dblDenom = dblB * dblB + dblA * dblA * Tan(dblTheta * DegToRad) * Tan
(dblTheta * DegToRad)
'calculate the absolute value of x and y
dblAbsX = (dblA * dblB) / Sqr(dblDenom)
dblAbsY = dblAbsX * Abs(Tan(dblTheta * DegToRad))
Select Case dblTheta
Case Is < 90#:
dblX = dblAbsX
dblY = dblAbsY
Case Is < 180#:
dblX = -dblAbsX
dblY = dblAbsY
Case Is < 270#:
dblX = -dblAbsX
dblY = -dblAbsY
Case Else
dblX = dblAbsX
dblY = -dblAbsY
End Select
End Function

Public Function GetReferenceAngle(dblTheta As Double, dblX As Double,
dblY As Double, dblA As Double, dblB As Double) As Double
Dim dblReferenceAngle As Double
Const DegToRad = 0.0174532925

GetReferenceAngle = 0
If dblTheta = 0 Or dblTheta = 360 Then
GetReferenceAngle = 90
Exit Function
End If
If dblTheta = 180 Then
GetReferenceAngle = -90
Exit Function
End If
GetReferenceAngle = Atn(dydx(dblA, dblB, dblX, dblY)) / DegToRad
End Function

Public Function dydx(dblA As Double, dblB As Double, dblCurX As
Double, dblCurY As Double) As Double
dydx = -dblB * dblB * dblCurX / (dblA * dblA * dblCurY)
End Function

Public Function GetBezierAngle(dblTheta As Double, dblReferenceAngle
As Double, strAlphaBeta As String) As Double
GetBezierAngle = 0
If dblTheta > 360 Then dblTheta = dblTheta - 360
If strAlphaBeta = "Alpha" Then
Select Case dblTheta
Case Is < 180:
GetBezierAngle = dblReferenceAngle + 180#
Case Else
GetBezierAngle = dblReferenceAngle
End Select
Else
Select Case dblTheta
Case Is < 180:
GetBezierAngle = dblReferenceAngle + 180#
Case Else
GetBezierAngle = dblReferenceAngle
End Select
End If
End Function

Note: It turned out not to be necessary to get the "Alpha" Bezier
angles, so strAlphaBeta and it's code can be removed for the "Alpha"
case.

James A. Fortune
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top