Quickly rasterize parts of PDF with Ghostscript - c#

In my C# application I am trying to show a PDF document in a navigatable window with options to zoom, pan, etc. I'm using Ghostscript.NET. It looks like for example Adobe Acrobat Reader is able to render just the given portion of a page, judging by the speed it is going at. I only found the means to rasterize entire page, which is not too practical, especially in high zoom levels. Is it possible to first crop out a rectangle (based on calculated corner coordinates) and then quickly rasterize it without the rest of the page?
I tried following command:
gswin64.exe -sDEVICE=pdfwrite -o C:/work/marked.pdf -dUseCropBox -c "[/CropBox [300 400 400 600] /PAGES pdfmark" -f "c:\big boat.pdf"
Which works, technically speaking, but as far as i understood, the document must be defined without its own crop box, otherwise it won't work.

In order to add a CropBox (to a page) you can use an EndPage procedure, by sending a pdfmark at the end of the page, instead of the beginning, it should overwrite any pre-existing CropBox.
Or more simply, you can simply render a portion of the media directly, which sounds like what you want to do in the first place and avoids a (potentially lengthy) processing step.
Set the media size to the area you want to be rendered. For now lets assume you want a 2 inch square, 1 inch up from the bottom of the page. So we start by making the media size 2 inches square, and fixing it so any input can't change it:
-dDEVICEWIDTHPOINTS=144 -dDEVICEHEIGHTPOINTS=144 -dFIXEDMEDIA
If you add that to the command line you use to render the PDF file you will see that you get a 2 inch square rendered. Of course right now that's the bottom left corner of the page, so now we need to shift the media position so that the portion we want lies on the page. To do that we use PostScript, specifically the PageOffet key in the page device dictionary:
<</PageOffset [-72 0]>> setpagedevice
Note that we are shifting the bottom left corner of the page, which is why we use -72, we want the corner to go down.
because we are using PostScript we need to introduce it with the -c and -f switches:
-c "<</PageOffset [-72 0]>> setpagedevice" -f
So the whole command line becomes:
./gs -dDEVICEWIDTHPOINTS=144 -dDEVICEHEIGHTPOINTS=144 -dFIXEDMEDIA -c "<</PageOffset [-72 0]>> setpagedevice" -f input.pdf
If you really want to add a CropBox and produce a PDF file then you need to add an EndPage procedure, which will add a CropBox to every page individually:
./gs -sDEVICE=pdfwrite -o ./marked.pdf -c "<</EndPage {0 eq {[/CropBox [300 400 400 600] /PAGE pdfmark pop true}{pop false}ifelse}>>setpagedevice" -f "c:\big boat.pdf

Related

C#: How can I save a portion of the Command Screen for later use?

I'm learning how to code C# from scratch. Right now, I'm learning how to build a scene on the command line and update it as necessary.
Part of what i want to do is to "scroll text as it is generated".
The scene is a square command line (Size 100 by 40) and outlined by a box of "#" characters. This is the canvas on which everything is presented.
As the user interacts via simple inputs, the program will provide textual feedback, like a text-based game.
However, unlike a normal text-based game, I cannot allow for the natural flow of the command line to move the canvas. In other words, if I allow for the command line to act naturally, then the canvas would slowly travel upwards until it's no longer visible.
I need a way to read whatever is already being presented on the screen and storing it on memory. Then, I can delete a portion of the screen an paste the previously copied information shifted upwards, making space for new information.
Here is a mockup of what I want to do:
Image 1: desirable outcome
My question is: Is there a way to "read" only a specific portion of the command space and store into memory?
I know you can store whatever is being printed at the moment of printing, or I could keep track of a certain number of previously displayed information and print it again, but I would like to "copy, then paste shifted" a portion of the screen.
PS: This is what I'm trying to avoid
Image 2: Undesirable outcome
Since the top line needs to be moved too, really the only way to do this is to clear the screen and redraw everything. Instead of printing directly to the screen, save the new line to a list, clear the screen, then print that list to the screen, together with the border.
While I haven't found a way to store a portion of the command line to a variable for later use, I've succesfully "scrolled" the text, and found a workaround to "store" it.
Simply put, Console.MoveBufferArea() allows one to select a portion of the command line buffer and move it somewhere else on the buffer.
This way I can:
-Clear whatever space i need at the top by moving the cursor to, say, (1,1) and writing a box of spaces via a string.
-Console.MoveBofferArea() the portion of the buffer a few rows upwards
-Write the new text at the bottom
As a byproduct, i can also "store" a portion of the screen for late use by:
-Setting the buffer to a wider area with Console.SetBufferSize()
-Use Console.MoveBufferArea() to the buffer portion that is outside of normal view
-Do whatever i need to do on the screen
-Use Console.MoveBufferArea() to retrieve the "stored" portion back to where i need it
-Reduce the buffer area (I could also just leave it be)

How can i write a line in a pdf with a gradient with ghostscript/postscript with tiffsep1 device?

I'm tring to modify a pdf with ghostscript via a ps file for add a transversal line, but it don't work for this file.
Input files
B&W pdf
Gradient pdf
I tried:
gs -sDEVICE=tiffsep1 -sCompression=lzw -r300x300 -o out%d.tif post.ps input.pdf
post.ps:
%!
<<
/BeginPage {
newpath
0 0 moveto
1000 1000 lineto
stroke
} bind
/Orientation 3
>> setpagedevice
The black output for my B&W pdf do have the line, but the black output for the Gradient pdf don't have it.
The line seems to be under the pdf!?
The /Orientation for both outputs is correct.
How can I get the expected output for my file with a gradient?
.
I'm calling gs in c# the same way as in this question.
The content of your PDF files contains no transparency operations, so they are opaque. In the case of your B&W file the only marks made on the page are the black areas, in the case of your Gradient file, almost the entire page is marked by the gradient fill.
The BeginPage PostScript procedure is executed at the beginning of the page, before the page contents are processed.
So what happens is that a black line is drawn, then the black marks from the B&W file are drawn. Where the black line is not covered by the black areas of the page contents you can see the line (had you drawn the line in, say, red, you would see where the black areas cover the line).
Your gradient file covers the entire area where the initial black line was drawn, so you can't see any of it.
If you want the line drawn 'on top' of the page content, then you need to use an EndPage procedure, not a BeginPage.
This case was reported as a bug in Ghostscript.
https://bugs.ghostscript.com/show_bug.cgi?id=702597
In fact, the supplied /EndPage procedure was invalid.
/BeginPage and /EndPage procedures are not interchangeable.
See PostScript Language Reference Manual, "6.2.6 Device Initialization and Page Setup" for details.

How To Remove Black Bars from Videos using VLC Control C#

I have created vlcControl added on my windows form. I would like to know how can get rid of black bars on my vlc videos (image consumes black space). An example is shown below:
I have tried the line vlc --aspect-ratio 16:9 -L -f /directory/to/file/filename.
The line changes the aspect ratio but did not work as expected. I have tried the following lines of code:
Line 1:
vlcCustomer.Play(new Uri("rtsp://192.168.1.10/2/media/video1"), ":network-caching=50 :aspect-ratio=16:9 -L -f /directory/to/file/filename");
Line 2:
vlcCustomer.Play(new Uri("rtsp://192.168.1.10/2/media/video1"), ":network-caching=50 vlc --aspect-ratio 16:9 -L -f /directory/to/file/filename");
No need to use CLI args for this, libvlc has an API for changing aspect ratio and it is available in Vlc.DotNet. Example: https://github.com/ZeBobo5/Vlc.DotNet/blob/f0d3e2aca37500ccd2710c8b9b286ccc485f1636/src/Samples/Samples.WinForms.Advanced/Sample.cs#L167
The thing is that your control will have the same size, whatever the aspect ratio you give to it, and it will need to fill with black bars. to get rid of it, you will need to resize your control and center it based on the aspect ratio you can get from the media info.
Modify this code according to your screen and paste after your code:
VideoWidth = "1280";
VideoHeight = "750";
VlcControl2.Video.AspectRatio = VideoWidth + ":" + VideoHeight;

Ghostscript clips a pdf file

I'm trying to print a pdf with Ghostscript using those settings :
var switches = new List<string>
{
#"-empty",
#"-dPrinted",
#"-dNOPAUSE",
#"-dNOSAFER",
#"-dQUIET",
#"-dPDFSETTINGS=/printer",
#"-dNumCopies=1",
#"-sDEVICE=mswinpr2",
#"-dCompatibilityLevel=1.4",
#"-sOutputFile=%printer%" + printerSettings.PrinterName,
#"-f",
pdfFileName
};
but either the pdf or Ghostscript have bad margins and while it's good when I print it to file it clips when I print it on my printer.
Is there any way to add those programatically with Ghostscript ? I tried many different solutions from first pages of google but none of them work and they seem to have no effect on the printed pdf.
When I try to print it out with Adobe or IE it magicaly adds margins as soon as I choose the printer and it prints fine.
How to achive the same with Ghostscript ?
OK well the first thing is that many of the switches you are setting have no effect:
-empty isn't a Ghostscript-understood switch, and I'm slightly surprised it doesn't cause an error.
-dPDFSETTINGS only affects the pdfwrite device, which is why it is documented in the vector devices section.
-dCompatabilityLevel only affects the output of the pdfwrite device.
-dNOSAFER doesn't have any effect, as that's the default setting.
-f is used to 'close' direct PostScript insertion begun with -c, if you don't use -c you don't need -f
Now almost certainly neither Ghostscript nor your PDF has 'bad margins', the most likely explanation for your problem is that the printer you are using cannot print to the boundaries of the page, the left/right edges, and potentially the top and bottom edges are used by the paper transport mechanism, and the printer cannot print there.
In order to deal with that, you will need to reduce the size of the image, which you can 'probably' do by setting -dDEVICEWIDTHPOINTS and -dDEVICEHEIGHTPOINTS and -dFIXEDMEDIA. Its going to be up to you to work out the correct values for width and height.
Added after the comments below
There are two parts to this problem, the first is to deduce the size of the actual available area to print on, and to scale the output to that size. The second is to then reposition the output on the media so that it is all printed. If as you say the content is significantly smaller than the media then you can ignore rescaling it, but the entire solution is presented here for completeness.
Now as previously mentioned, the first part of this is achieved primarily by creating a fixed size canvas; this is done with any of the media selection switches and the addition of -dFIXEDMEDIA.
NOTE if you alter the media size, then you must, obviously, also alter the scale of the contents, or it won't fit. So you also need to set PSFitPage, EPSFitPage or PDFFitPage depending on the type of input (very recent versions of Ghostscript can use -dFitPage no matter what the input type).
As an experiment I used the file /ghostpdl/examples/text_graphic_image.pdf and sent the output to a printer on FILE:
This command line:
gswin32 -dDEVICEHEIGHTPOINTS=391 -dDEVICEWIDTHPOINTS=306 -dFIXEDMEDIA -sDEVICE=mswinpr2 -sOutputFile=%printer%KensPrinter /ghostpdl/examples/text_graphic_image.pdf
produces output where 3/4 the image is clipped away (the content lies off the newly defined fixed canvas size). If I modify that to:
gswin32 -dDEVICEHEIGHTPOINTS=391 -dDEVICEWIDTHPOINTS=306 -dFIXEDMEDIA -dPDFFitPage -sDEVICE=mswinpr2 -sOutptuFile=%printer%KensPrinter /ghostpdl/examples/text_graphic_image.pdf
then the result is a perfect reproduction of the original, at 1/4 the size (half in each direction).
So, the first thing you need to do is establish the actual printable area of the media on your printer, then you can set the width and height correctly as fixed media, and tell Ghostscript to scale the page to fit.
However, this will still leave the printed image at the bottom left of the media. Since that's in an area that can't be printed, you need to shift the printed image until its centred on the page. As I suggested, you can do this with a BeginPage procedure. This:
gswin32 -dDEVICEHEIGHTPOINTS=391 -dDEVICEWIDTHPOINTS=306 -dFIXEDMEDIA -dPDFFitPage -sDEVICE=mswinpr2 -sOutptuFile=%printer%KensPrinter -c "<</BeginPage {100 100 translate}>> setpagedevice" -f /ghostpdl/examples/text_graphic_image.pdf
produces output where the printed image is shifted up and right by 100 points each.
I believe that a little investigation will allow you to figure out where exactly your printer is able to print, and to create appropriately sized unprintable margins.
Note that, for me, the %printer% syntax does not result in a printer selection dialog. I suspect that your code (whatever language that is) is expanding the %p, resulting in a corruption of the name. Or possibly whatever you use to fork a Ghostscritp process does it. In either event you probably need to double the % signs.
You should get this working from the command line first, then work on getting it into an application.

Creating custom size PDF document with Debenu Quick PDF

Hi I am using Debenu Quick PDF Lib.
I couldn't see any sample or info about creating custom size PDF document.
For example I want to create a new document in size of 80mm x 100mm in 300 dpi. Is that possible with QP ?
Thank you .
user3253797,
QP.SetMeasurementUnits(1); // Set the measurement units to mm
QP.SetPageDimensions(80.0, 100.0); // Set the page size to 80mm x 100mm
In a PDF file there is no DPI value as nearly all the values in a PDF are based on floating point numbers.
When SetMeasurementUnits is set to 1 then all values you use for drawing are assumed to be in millimetres. ie. QP.DrawLine(0, 0, 25.4, 25.4); will draw a diagonal line from the bottom left corner (0,0) to a point 1 inch up and 1 inch to the right of the bottom corner of the page. If you need the Origin to be based a the top right then you need to call QP.SetOrigin(1); first.
Also, the "Debenu Quick PDF Library 10 Developer Guide.pdf" is the perfect place to start to learn about Debenu Quick PDF Library. It explains the basics of creating PDF files using the library and some of the fundamentals of PDF files.
Andrew.
Disclaimer: I work for Debenu.

Categories