0
votes

I try to add crop marker in pdf file. But crop marker not set in right side or top side in proper corner. I try to get page size and set marker by postscript but my postscript get new page width and height and set marker but marker position not right. My ghost command is :- gswin64c.exe -o E:\output.pdf -dBATCH -dNOPAUSE -dDOPDFMARKS -sDEVICE=pdfwrite -dFIXEDMEDIA -dPDFFitPage -dDEVICEWIDTHPOINTS=396 -dDEVICEHEIGHTPOINTS=612 test.ps -f E:\comic.pdf

Both inout or output file link Input PDF Output PDF

and my postscript for crop marker is

    <<
/BeginPage {
    /count exch def % of previous showpage calls for this device
} bind
/EndPage {

    /pagewidth  currentpagedevice /PageSize get 0 get def
    /pageheight currentpagedevice /PageSize get 1 get def
    /y pageheight 9 sub def
    /x pagewidth 9 sub def

    newpath
    -1 -1 moveto
    0 9 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    grestore
    1 setlinewidth
    stroke


    newpath
    x -1 moveto
    0 9 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    1 setlinewidth
    grestore
    stroke


    newpath
    x y moveto
    0 10 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    grestore
    1 setlinewidth
    stroke

    newpath
    -1 y moveto
    0 10 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    grestore
    1 setlinewidth
    stroke


    % return (output=) true only for showpage.
    code 0 eq
}
>> setpagedevice
3
What are your requirements? Are there many pdf files to convert? Is the initial size always the same 496x756? Is the final size always 396x612? Your command line always sets the interpreter to create a 396x612 output so that doesn't care about the input size and so that information is ignored. These examples put the crop marks on the page before the actual resizing of the original to the new PageSize which evidently must be after the EndPage is finished. I have found a 2 step distilling process works to first place the crop marks and then resize the page. Does that work for your purposes?beginner6789

3 Answers

1
votes

Ideally you should not simply create new key/value pairs in whatever the current dictionary happens to be when you run the BeginPage or EndPage procedures. The reason is that you can't rely on exactly which dictionary happens to be on the top of the dictionary stack at the time these are executed, and it can be different.

This can lead to the keys you expect to be present not being defined, and can (potentially) lead to you overwriting keys/value pairs already in the dictionary.

In fact it's usually regarded as better practice, in PostScript, not to define transient variables in a dictionary at all, but simply to store them on the stack and access them from there. This negates the possibility of overwriting values, and stack operations are usually faster than dictionary operations, so there's a (slight) performance benefit as well.

Your EndPage procedure performs all the calculations and executes the stroke, even when it's not going to transmit the page to the device, which is clearly wasteful, you should use an if instead. You are using gsave and grestore together as a pair, that's pointless and very expensive performance wise. That's a save and restore of the graphics state, if you don't do anything in between then it has no effect.

Finally your BeginPage procedure defines /count but you don't appear to actually do anything with it!

If I were you I would rewrite these as:

/BeginPage {
    userdict /MyDict known    %% is MyDict alreadly present in userdict ?
    {
        userdict /MyDict get  %% If it is, then get it
    }
    {
        userdict begin        %% start userdict (makes it top element on dict stack)
        /MyDict               %% Put key /MyDict on stack
                              %%   stack - /MyDict
        5 dict                %% make a 5 element dictionary
                              %%   stack - /MyDict -dict-
        dup                   %% make a copy (duiplicates a pointer)
                              %%   stack - /MyDict -dict -dict-
        3 1 roll              %% rotate the stack
                              %%   stack -dict /MyDict -dict
        put                   %% Put the top element on the stack in the current
                              %% dictionary, using the key second top on the stack
                              %%    stack -dict-
        end                   %% close userdict
    } ifelse
    begin                     %% make the top element on the stack the current
                              %% dictionary.
    /count exch def           %% store the count ot pages in the currnt dictionary
                              %% using the key /count.
    end                       %% close the current dictionary
}

Obviously you can drop all the comments, they are purely explanatory. From this point on you can find the value associated with count by doing:

userdict /MyDict get /count get

Then:

/EndPage {
                                 %% We enter with the reason code on the stack
    0 eq {                       %% We only want to take action for 0 (showpage)
      gsave
      currentpagedevice          %% Get the current page device dictionary
                                 %%    stack -dict-
      /PageSize get              %% get the value associated with the key /PageSize
                                 %% from that dictionary.
                                 %%    stack -array-
      dup dup                    %% make some copies of the array
                                 %%     stack -array- -array- -array-
      0 get                      %% get element 0 from the array
                                 %%     stack -array- -array- 'x'
      9 sub                      %% subtract 9 from the value
      0 put                      %% put that into array element 0
                                 %%      stack -array-
      dup dup 1 get              %% repaeat for element 1
      9 sub 1 put

      newpath
      -1 -1 moveto
      0 9 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath

      dup 0 get                  %% duplicate the array, get the 0th element
      -1 moveto                  
      0 9 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath
      
      dup 0 get                  %% duplicate the array, get the 0th element
                                 %% stack -array- 'x'
      1 index                    %% copy the element one down the stack to the top
                                 %% stack -array- 'x' -array-
      1 get                      %% get element 1 of the array
                                 %% stack -array- 'x' 'y'
      moveto
      0 10 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath

      1 get                      %% get element 1 from the array
      -1 exch moveto
      0 10 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath

      1 setlinewdith
      stroke

      grestore
      true
    }
    {
      false
    }ifelse
}

Note that I have not tested the code, it's just there for illustration.

Now the real point of this is that the reason your strokes are misplaced is because you have scaled the page.

-dFitPage works by adjusting the Current Transformation Matrix to scale the page contents so that they fit into the new page dimensions. Everything after that point will be scaled, and this includes the path construction in your EndPage procedure.

To demonstrate; try executing the command line without -dFIXEDMEDIA etc and you should see that the page comes out the original size and with the strokes in the correct place.

In order to place the strokes correctly you need to know what scale factor has been applied and multiply the co-ordinate values by the inverse of that amount. That is, if the scale factor was 0.5 (ie half size) you would need to multiply the positions by 2.

0
votes

This was fun. Tested to put crop marks only and without errors yet still without inverse scaling so not for instant resizing. The decision to move to a two step re-distilling would depend on the requirements since the two step approach works now while additional development could achieve all-in-one results in the future.

<<  /EndPage { exch pop   % page number unneeded

0 eq { pop       % ifelse

gsave

currentpagedevice /PageSize get
dup 0 get 9 sub exch 1 get 9 sub

2 array astore       % put in new array

newpath
-1 -1 moveto
0 9 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

newpath
%    x
dup 0 get
-1 moveto
0 9 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

newpath
%    x y 
dup aload pop
moveto
0 10 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

newpath
1 get
%    -1 
%    y
-1 exch
moveto
0 10 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

grestore

% return (output=) true only for showpage.
true}{pop false}ifelse

}
 >> setpagedevice

%showpage   % shortcut for testing

EDIT: Here are the two steps:

gs -o comic11-cropmarks.pdf -dBATCH -dNOPAUSE -dDOPDFMARKS -sDEVICE=pdfwrite cropmarks1.ps -f comic11.pdf
gs -o comic11-resized.pdf -dBATCH -dNOPAUSE -dDOPDFMARKS -sDEVICE=pdfwrite -dFIXEDMEDIA -dPDFFitPage -dDEVICEWIDTHPOINTS=396 -dDEVICEHEIGHTPOINTS=612 -f comic11-cropmarks.pdf

EDIT2: These redistillings cause the dpi to change so if the 300dpi resolution is needed then that can be altered with ghostscript also. Here is some info about the results of the two step process:

$ pdfimages -list comic11.pdf tmp/
tmp/-0000.ppm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceRGB bpc=8
tmp/-0001.pgm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceGray bpc=8

$ pdfimages -list comic11-cropmarks.pdf tmp/
tmp/-0000.ppm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceRGB bpc=8
tmp/-0001.pgm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceGray bpc=8

$ pdfimages -list comic11-resized.pdf tmp/
tmp/-0000.ppm: page=1 width=2063 height=3150 hdpi=375.09 vdpi=375.09 colorspace=DeviceRGB bpc=8
tmp/-0001.pgm: page=1 width=2063 height=3150 hdpi=375.09 vdpi=375.09 colorspace=DeviceGray bpc=8
0
votes

Here is an all-in-one solution. I had to change the ghostscript command line.

EDIT: Here is a postscript all-in-one comic.ps because you said the page size didn't work for my previous attempt:

%!
true setstrokeadjust
0.5 setlinewidth 1.0 0.9 0.9 setrgbcolor
[ 7.7 10 381 591 ] dup rectfill
1 0 0 setrgbcolor rectstroke 0.9 0.9 1.0 setrgbcolor
[ 15 18 366.5 575.5 ] dup rectfill
0.3 setlinewidth 0 0 1 setrgbcolor rectstroke
0 0 0 setrgbcolor
[ 7.7 10 -10 -10 ] rectstroke
[ 7.7 601 -10 10 ] rectstroke
[ 388.5 601 10 10 ] rectstroke
[ 388.5 10 10 -10 ] rectstroke

/centre { dup stringwidth pop 2 div 396 2 div exch sub } def
/Helvetica-BoldOblique 10 selectfont

(ARTWORK MUST EXTEND PAST RED LINES ON ALL PAGES.) centre 500 moveto show
(THIS IS THE TRIM LINE.) centre 478 moveto show
(ARTWORK BEYOND THE TRIM LINE WILL FALL INTO SPINE) centre 456 moveto show
(OR BE CUT OFF. THE ACTUAL CUT MAY VARY UP TO 1/8" FROM) centre 434 moveto show
(THIS LINE TO EITHER SIDE DURING PRODUCTION.) centre 412 moveto show
(BLUE AREA IS THE "SAFE" ZONE.) centre 390 moveto show
(BE SURE ALL TEXT AND IMPORTANT IMAGES ARE) centre 368 moveto show
(KEPT WITHIN THE BLUE AREAS.) centre 346 moveto show
(ALL NON-WHITE BORDERS AND FILLS) centre 324 moveto show
(SHOULD EXTEND TO EDGE OF PAGE. \(WHITE AREA\)) centre 302 moveto show
(TEMPLATE RESOLUTION IS SET TO 300 DPI.) centre 280 moveto show
(THIS IS PRINT-READY AND SHOULD NOT BE CHANGED.) centre 258 moveto show
1 0 0 setrgbcolor
(THESE NOTES ARE ON THE "TEMPLATE" LAYER) centre 136 moveto show
(AND SHOULD BE DELETED BEFORE EXPORTING) centre 114 moveto show
(FINAL FILES FOR PRINT.) centre 92 moveto show
showpage

This is just an example. The postscript can be edited to fix any other problems. Here is my ghostscript command line:

gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -r300 -dPDFFitPage -dFIXEDMEDIA -dDEVICEWIDTHPOINTS=396 -dDEVICEHEIGHTPOINTS=612 -sOutputFile=comic.pdf -f comic.ps

EDIT3: Fixed the numbers found by overlaying the above postscript rectangles onto the resized comic11.pdf until they matched.

EDIT4: Adding "<< /PageSize [396 612] >> setpagedevice" to the beginning of the above postscript allows a pdf to be created with the correct page size using ps2pdf.