Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reducing PDF size when distilling PS with EPS Forms

Status
Not open for further replies.

armentage

Programmer
Mar 11, 2004
8
US
I have a PS file with an embedded EPS image. I used Tgreer's great ReusableStreamDecode posts in the Postscript forum as a reference, and am creating using the images on a per-page header by doing

save
100 100 translate
MyLogoForm execform
restore

The PS output looks great, however I'm running into problems when I convert to PDF using the Ghostscript PS2PDF program. The header image adds 5k bytes to my PDF file, for EACH page it appears on. 10 empty pages are 50k, 25 pages are 125k, etc.

Is there anything I can do to reduce the size of my output? I had thought that embeddeding the image as a form would result in references to the embedded image, but that doesn't seem to be the case.
 
A couple of things.

Ideally, the translates and scales needed to properly place a form should be in the form's PaintProc.

I know, I know, my examples don't all show that. This is a techinical point when it comes to RIP performance, and may not have anything to do with you particular problem.

To the point:

PDF has a "form" structure analagous to the PostScript "form" structure. Meaning, that an image need only be in the PDF once, and then simply referred to when needed, rather than being included.

That doesn't mean that GhostScript does things that way! What can you do? Two things come to mind. One, use something besides GhostScript. Distiller, or activePDF Server, depending on workflow and pocket book.

Second, open the PDF in Acrobat, and perform a "save". Acrobat should re-write the PDF to a more efficient format.



Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
I got my hands on a copy of Acrobat5 and used it to distill my PS input. The output was MUCH smaller, so you're right about Ghostscript sucking.

I guess I'll have to get my company to spring for the Unix version of Distiller.

Unless anyone happens to know of a Free PDF C/C++ writing library ...
 
Such libraries abound. They aren't going to give you much flexibility. But very few people need as much flexibility as I do for the type of work I do, so I try not to judge :)

Search PDFZone and PlanetPDF.





Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
Well, I've gotten my hands on a copy of Distiller (on UNIX) but I'm getting an error distilling my file:

Distilling test.ps (115,245 bytes)
%%[ Error: undefined; OffendingCommand: filter ]%%

Stack:
/ReusableStreamDecode
-dict-
-file-
/ImageData


%%[ Flushing: rest of job (to end-of-file) will be ignored ]%%
%%[ Warning: PostScript error. No PDF file produced. ] %%
0.2 seconds (0:00)


Here's how what my file looks like:
%!PS

/ImageData
currentfile
<< /Filter /SubFileDecode
/DecodeParms << /EODCount 0 /EODString (*EOD*) >>
>> /ReusableStreamDecode filter
%!PS-Adobe-3.0
% ... EPS contents are here ...
%%EOF
*EOD*
def

/IDForm
<< /FormType 1
/BBox [0 -1 86 36]
/Matrix [ 1 0 0 1 0 0]
/PaintProc
{ pop
/ostate save def
/showpage {} def
/setpagedevice /pop load def
ImageData 0 setfileposition ImageData cvx exec
ostate restore
} bind
>> def

save
0 0 translate
IDForm execform
restore
showpage

save
100 0 translate
IDForm execform
restore
showpage



This file distill's fine with the Windows Distiller... any ideas?
 
What version of Distiller? ResuableStreamDecode is a PostScript Level 3 filter. The error is telling you that the "filter" operator doesn't like what it's being asked to handle, which in this case is /ReusableStreamDecode.

There is a way to do this in Level 2 code, if that's a necessity.

It involves reading your EPS as a large array of strings, and then executing those strings.

Code:
%!PS

%%TGREER: start of form code for EPS, Level 2 code
userdict /forms_ops 10 dict dup begin put
/StartEPSF
{ userdict begin
  /PreEPS_state save def
  /dict_stack countdictstack def
  /ops_count count 1 sub def
  /showpage {} def
  /LH {} def
  /setpagedevice /pop load def
} bind def

/EPSFCleanUp
{ count ops_count sub {pop} repeat
  countdictstack dict_stack sub {end} repeat
  PreEPS_state restore
  end 
} bind def

/STRING_SIZE 16000 def
/ARRAY_SIZE 40 def
/buffer STRING_SIZE string def
/inputFile currentfile 0 (*EOD*) /SubFileDecode filter def

/readdata
{ 1
  { 2 copy 
    inputFile buffer readstring
    4 1 roll
    STRING_SIZE string copy put
    not {exit} if
    1 add
  } loop
  1 add 2 copy () put pop
  currentglobal true setglobal exch
  0 1 array put
  setglobal
} bind def
currentdict readonly pop end

<< /MaxFormItem currentsystemparams /MaxFormCache get >> setuserparams
forms_ops begin
userdict begin

/underlayForm
  10 dict begin
  /FormType 1 def
  /EPSArray ARRAY_SIZE array def
  /AcquisitionProc
  { EPSArray dup 0 get dup 0 get
    dup 3 1 roll
    1 add 0 exch put
    get
  } bind def

  /PaintProc
  { begin
    StartEPSF
    10 700 translate %%TGREER: edit this
    EPSArray 0 get 0 1 put
    //AcquisitionProc 0 () /SubFileDecode filter
    cvx exec
    EPSFCleanUp
    end
  } bind def

  /BBox [ 0 0 612 792] def
  /Matrix [1 0 0 1 0 0] def
  currentdict end
def

underlayForm /EPSArray get
readdata
%%TGREER: end of form embedding code
%%TGREER: put your logo EPS below
%%TGREER: put your logo EPS above
*EOD*

underlayForm execform 
[code]


Thomas D. Greer
[URL unfurl="true"]http://www.tgreer.com[/URL]
Providing PostScript & PDF
Training, Development & Consulting
 
Thanks for the fast replies, Tgreer

You might want to consider making these posts FAQ entries, since the question of embedding EPS into PS seems to come up so often!
 
So while I've got your attention here...

I'm now trying to embed TWO EPS files into my report. I read through the code you posted (the one that uses a buffer and parses it line-by-line), duplicated it. I changed the names of /def'd entities (like EPSBuffer, readData, etc) and def'd it all as a 2nd form. Any pitfalls I need to watch out for?

I'm having trouble with it right now, but I think my 2nd EPS file might not be well formed. It's BoundingBox has it starting near the center of the page, and no transform's seem to bring it into the visible page area.
 
You don't need to change the names of procedures. For example, readData. It's a generic procedure. Basically, you need to alter the contents of InputFile.

The pitfall is that the filters process "currentfile", through the *EOD* marker. So it matters where you place your definitions of the filtered files.

You can also place both EPS files next to each other, in the file, one after the other, and place some basic PostScript wrappers around them, and treat the whole structure as a single form. That wasn't very clear... above where I have the two comments for "Place EPS here"?, you can place BOTH eps files. You have to add some code between them, namely "EPSFCleanUp x y translate StartEPSF". The x y translate, you'd put real numbers there to position the second logo.

With EPS files that have altered Bounding Boxes, (those which don't start "0 0", you can do two translates. The first to negate the bad offset, the second to do your final positioning.

For example, if your bounding box is "72 144 100 200", you can first do "-72 -144 translate", followed by another translate to put the EPS where you want it.





Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
Due to the way the PS file is already structured, combining both EPS into one form is going to be a little tricky. The PS file is generated by a reporting library, that does all sorts of weird things with page orientations and layout. I'm not really comfortable enough with PS to significantly change how its generated, so I'm trying to execForm my logos over the existing header & footer areas.

Thing you could show me how to load both EPS files as seperate forms? I've tried this:

/logo1Form
%% PaintProc and related code
def

/logo2Form
%% PaintProc and related code
def

logo1Form /EPSArray get
readdata
%...
*EOD*

logo2Form /EPSArray get
readdata
%...
*EOD*


When I do this, I end up with the 2nd EPS file executing itself onto the page, and rendering stops.
 
I'd be happy to take a look at it. Frankly, I haven't tried to fully embed, with Level2 code, two EPS files as reusable forms before. So if you can, email me the master PostScript form, and both EPS files? Along with a description of where you want the EPS files to appear on the page?

You can get my email address from my webpage.



Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top