Set background color in postscript - postscript

I want to change the postscript background color from white to black, and this is the ps file:
%%Page: 1 1
%%BeginPageSetup
%%PageOrientation: Landscape
pdfStartPage
0 0 540 720 re W
%%EndPageSetup
[] 0 d
1 i
0 j
0 J
10 M
1 w
/DeviceGray {} cs
[0] sc
/DeviceGray {} CS
[0] SC
false op
false OP
{} settransfer
q
q
1 i
0 0 540 720 re
W*
0 0.03 540 720 re
W
/DeviceRGB {} cs
[0 0 0] sc
[1 1 1] sc // it means [R G B] (range: from 0.0 to 1.0)
... e.g. if it is changed to [0.5 0.5 0.5]
, then the background color is grey
At the last two lines, they're totally the same; only the last line can change the background color, but the second last line can't. Why?

Well what you have there is only part of a PostScript program. It looks to me like its been converted from a PDF file, because the operators are PDF operators, not PostScript ones. Also 'pdfStartPage' is a bit of a giveaway.
PostScript has no concept of a 'background colour'. There are portions of the page which are marked, and portions which are unmarked, that doesn't make them 'white' though, it makes them unmarked. Viewers will normally render unmarked portions as white, but that's not quite the same thing. Rendering to white (ie 0 setgray 1 1 1 setrgbcolor or 0 0 0 0 setcmykcolor) will cause a printer not to print those areas. If you actually want to write white ink then you need to use a Separation colour named /White.
If you put a piece of paper into a laser printer, and print to it, only the marked areas will be printed. If your paper is white then the unmarked areas will be white. If your paper is (for example) yellow, then the unmarked areas will be yellow.
Anyway, its not really possible to comment on what your PostScript program is doing without seeing all of it, since it redefines operators.
The two lines you have marked do not change the 'background colour', they change the current colour. Any operations after that point will be in the new current colour. Again, its impossible to say what is changed since you haven't quoted any marking operations following that point.
If you really want to discuss the program, it would be best to post it somewhere public so people can look at the entirety of the program, not just a random small chunk.

Related

Get Vertices/Edges From BMP or SVG (C#)

I have a JPG, BMP, or SVG image (see example below) and I need an algorithm to extract the vertices (X, Y) coordinates and the egdes (i.e., a list that indicates which vertices are connected). The Edges can be of the form of a boolean true/false for each vertex pair or simply a list of vertex pairs that are connected. Any ideas welcome.
For example, I would like a function (or series of functions) which input the image and output two lists:
Vertices:
Vertex 1: X = 1, Y = 2
Vertex 2: X = 3, Y = 5
Vertex 3: X = 3, Y = 7
...
Edges:
Edge 1: (Vertex 1, Vertex 3)
Edge 2: (Vertex 1, Vertex 4)
Edge 3: (Vertex 4, Vertex 10)
...
The vertex coordinate system can be in any coordinate system (e.g., pixels, based on SVG coordinates) or it can be some alternate user-defined coordinate system.
For example, I extracted the following coordinates (pixels) from the example image (left) and plotting them in Matlab (right).
So, for example, I can tell that the corner vertices are roughly:
(10, 10), (290, 10), (290, 190), and (10, 190).
But I want an algorithm to automatically detect those coordinates and to also tell me that there is an edge between the top left vertex (10, 190) and the top right vertex (290, 190), etc. I also need to identify each of the vertices and edges for the internal blocks, etc.
As well, for more complicated diagrams, I need it to work as well. For example, I am able to extract the necessary pixels and produce the following Matlab plot:
Similarly to before, it is quite clear where the vertices "should be", however, due to the line thickness, there are many clusters of pixels that first need to be "smoothed out", etc. I'm unsure of how to go about doing this and automating the process of identifying vertices/edges.
Note 1: The method I'm using to get the pixel coordinates is basically:
Convert to Black/White
Scan each pixel to see if colour <= threshold, save (X,Y) if it's "black"
Plot in Matlab
A rough algorithm which I'm thinking is:
Apply "smoothing" to get a single line instead of pixel clusters
"Loop" through pixels in different directions, when a significant slope change occurs, Identify it as a "vertex"
After all vertices are identified, evaluate the line between each pair of vertices, if that line is mostly black, identify it as an edge
There are many issues with the above algorithm, so I was hoping others might have some better ideas or similar C# code, etc.
I would like the process to be as automated as possible.
Note 2: I can also convert the image to SVG format (already implemented). It is my understanding that the SVG format may lend itself very well to my application because it can more easily automate the process; however, I find the SVG structure quite confusing.
I have read through some literature online about SVG formats and I understand how it works, but I was wondering if there was some sort of already existing library or something that would allow me to very easily identify the vertices of the "path" in the SVG file, etc.
For example, one of the "paths" that I get from one SVG file is of the form:
<path d="M70 1810 c0 -91 3 -110 15 -110 12 0 15 17 15 95 l0 95 1405
0 1405 0 0 -410 0 -411 -87 3 -88 3 -1 35 c0 19 -1 124 -2 233 l-2 197
-70 0 -70 0 0 -320 0 -320 153 0 c83 0 162 3 175 6 l22 6 0 504 0 504
-1435 0 -1435 0 0 -110z m2647 -490 c1 -113 2 -217 2 -232 l1 -27 88 -3
87 -3 0 -70 0 -70 145 0 -145 0 -3 295 c-1 162 0 301 3 308 3 9 21 12
57 10 l53 -3 2 -205z"/>
I know this follows a Cubic Bezier Spline, but I was wondering if any already existing algorithms are out there to process the "path" code and extract the relevant coordinates, etc.
Thanks for your help!!
SVG path parsing is not that hard (unless you have complex SVG which does not seem like the case)
find path
Path starts with <path tag and ends usually with /> so find the path start/end and then work only with the string inside.
find the d="
That is the path string data (so you skip formating etc ...) the end of this is marked with " so again work only with string inside
process the path string
read single character (skip spaces)
depending the character read the right count of numbers and add entity to your vector representation
for example:
M means absolute move so x,y follows so cursor = (x,y);
m means relative move so x,y follows so cursor+= (x,y);
L means absolute line so x,yfollows so add_line(cursor,(x,y)); cursor = (x,y);
l means relative line so x,yfollows so add_line(cursor,cursor+(x,y)); cursor += (x,y);
C means absolute BEZIER cubic so x1,y1,x2,y2,x3,y3 follows so add_cubic_BEZIER(cursor,(x1,y1),(x2,y2),(x3,y3)); cursor=(x3,y3)
etc ... the commands m,M,l,L,h,H,v,V,c,C,s,S,q,Q,t,T are different only in number of points and type of curve/line
z means just that you add line from cursor at the end to the start point
if next string is starting with number handle it as last command and goto #2
goto #1
That is all. So all you need is just simple string parsing capable of reading numbers in mantissa/exponent form like -125.547e-99 and skiping spaces/tabs. You do not need to decode the whole SVG just paths.
As you can have many paths per SVG then after parsing first <path find another parse it ... until no one is left. Sometimes the <path contains transform matrix or even the owner tag usualy <gso there may be stacked some transformations but I think your export is simple without such things.

C# Image to Postscript ends up off-center

I've created a library that can create a Postscript file from input data in C#. However, when creating images using the following code, the images are appearing incorrectly. It's like they're off-center. From left to right, you see the right edge of the image first and then the left of the image displays in the rest of the image's allotted space. For clarity's sake, it's like taking the word "hello," and instead displaying "ohell."
I'm using the following C# code to create a List object filled with lines that output directly to a postscript file. It looks pretty standard to me, although I noticed a couple of peculiarities that I had to code around. For some reason, my 75 width image wanted to display as 76 pixels in width, so I added the section to add a pixel to it. I don't know why this is, and I have not done enough testing yet to see what all this screws up. Additionally, normally, the Image Matrixes I use have negative height followed by height, but the image was appearing upside down, so I had to swap it.
public virtual List<string> AddImage(Image img, int x, int y, int height, int width)
{
string sDataSource;
List<string> destinationList = new List<string>();
int iImgWidth = img.Width;
if (iImgWidth % 2 != 0)
{
iImgWidth += 1;
}
using (MemoryStream ms2 = new MemoryStream())
{
Bitmap bmp = (img as Bitmap).Clone(
new Rectangle(0, 0, img.Width, img.Height),
PixelFormat.Format24bppRgb);
bmp.Save(ms2, ImageFormat.Bmp);
sDataSource = $"<{string.Join("", ms2.ToArray().Select(a => a.ToString("X2")))}>";
}
destinationList.Add($"{x} {y} translate");
destinationList.Add($"{width} {height} scale");
destinationList.Add(
$"/DeviceRGB setcolorspace {{ << /ImageType 1 /Width {iImgWidth} /Height {img.Height} /ImageMatrix [{iImgWidth} 0 0 {img.Height} 0 {img.Height}] /BitsPerComponent 8 /Decode [0 1 0 1 0 1] ");
destinationList.Add($"/DataSource {sDataSource} >> image }} exec ");
return destinationList;
}
I've got the output narrowed down to the following, and it's still displaying incorrectly.
%!PS-Adobe-3.1
0 649 translate
27 20 scale
/DeviceRGB setcolorspace { << /ImageType 1 /Width 76 /Height 56 /ImageMatrix [76 0 0 56 0 -56] /BitsPerComponent 8 /Decode [0 1 0 1 0 1]
/DataSource <... (hex code)> >> image } exec
showpage
Can anyone point me in the right direction? I've been struggling with this for days.
There are two likely possibilities, you've mentioned both of them in your post, but without the original image data its not possible to tell whether your suppositions are correct.
The first is that you've got the image upside down. In PostScript 0,0 is the lower left of the page, and increasing y moves up the page. Images normally start at the top left, and progress down the page.
So normally the image matrix would be [w 0 0 -h 0 h] whereas what you seem to be emitting is [w 0 0 h 0 -h]. Of course this could be correct, its not possible to be certain without knowing the progression order of samples in the original image.
Its also possible that you've got the bitmap data incorrect, or the width wrong (the fact that you have a width other than what you expected is suspicious), so that the PostScript interpreter starts with half a raster width of white. After that, it draws what you expect as the first (left) part of the image until it has read (and rendered) sufficient data for the whole raster line.
Then the interpreter moves to the next line of image and reads the following data. This data then consists of the right hand portion of the first raster line, followed by the left hand portion of the second line.
And so on. It then appears that the image has been wrapped round.
This is, of course, speculation, because you haven't supplied an example of the input data, or the final PostScript program. I'd suggest that you post an full example output somewhere and link to it here. The original image would probably be useful too, in order to demonstrate the original sample order.
[after looking at the files]
Well, starting from the JPEG, which I assume is the original file, I see that the data in your hex string does not match the data in the decompressed JPEG, nor what I would expect.
Given that most of the image is white, I would expect to see RGB triplets of 0xFF 0xFF 0xFF, your data beings with:
424D0E0901000000000036000000280000009600000096000000010018000000000000000000232E0000232E00000000000000000000
I've no idea what that is, but I'm reasonably confident its not part of the original image data. It looks like your hex string is 135710 bytes. Now, width of 150 * 3 bytes (for RGB = 450 * 150 for the height results in expected data of 67,500 bytes * 2 for hex representation means your data should be 135000 bytes. So it looks to me like your string 'probably' has about 710 bytes too many in it, or 118 RGB triplets too many. I may have screwed up some arithmetic there but that turns out to be everything up to the first 'FF' in your string which is suspicious :-)
I don't speak C# so I can't look at your code (in fact I can't even figure out from the SourceForge project where the actual code is). However it looks to me like you have a problem either decoding the JPEG or opening the output file or something. Removing the odd stuff at the beginning of the data stream doesn't solve the problem, but then I don't know how much is extraneous.....
Given the nature of this problem I think the first thing I would do is use some other tool to extract the image data (just the RGB triplets). Then have my own code write out the same data, ideally these should be identical, but there can be minor differences in JPEG dequantisation. However the data length should at least be the same and the content should be very similar.
There's some odd 'blue' pixels appearing at the edge of the image, I suspect there's something wrong with the decoding you are applying here. Looking at the original I cannot see where that effect is coming from, there is no vertical line in the original that I can see.
In passing you should be aware that some PostScript implementations have a limit on string lengths of 64KB, and your string is already over that limit. As a result your file won't run with Adobe Acrobat Distiller, or any other Adobe PostScript interpreter. If you want to create larger images, you are going to have to change your approach.

How to embed JPEG image in a postscript file?

I want to embed a JPEG to a postscript file. Is there any way to embed it directly like embedding a PS file?
72 300 translate
(incuse.eps) run
I was finally able to display an image using this code in ghostscript.
newpath
25 725 moveto
0 90 rlineto
120 0 rlineto
0 -90 rlineto
-120 0 rlineto
closepath
0 0 0 setrgbcolor
1 setlinewidth
stroke
gsave
25 700 translate
175 175 scale
800
808
8
[800 0 0 -808 0 0]
(ADSM_Logo.jpg) (r) file /DCTDecode filter
false
3
colorimage
grestore
showpage
but I have an error when I print the PS file.
Error Name: /undefined Offending Command: --file-- Operand Stack:
(r)
(ADSM_Logo.jpg)
[800 0 0 -808 0 0]
8
808
800
The Square gets drawn successfully but the image doesn't appear.
PostScript can handle DCT, so yes. You need to use the DCTDecode filter to decompress the image DataSource.
Look at viewjpeg.ps in Ghostscript's lib folder for a full program, but this is the basics:
% prepare image dictionary
<< /ImageType 1
/Width width
/Height height
/ImageMatrix [ width 0 0 height neg 0 height ]
/BitsPerComponent 8
% If 4-component (CMYK), assume data is inverted per Adobe Photoshop
colors 4 eq {
/Decode [ colors { 1 0 } repeat ]
} {
/Decode [ colors { 0 1 } repeat ]
} ifelse
/DataSource F /DCTDecode filter
>> image
Update
You are using the 'file' operator to read a file from disk, presumably you haven't stored this file on your printer's hard disk (if it even has one) so, unsurprisingly it doesn't work.
The error even says so (more or less) 'undefined' 'Offending command file' and on the top of the operand stack is '(ADSM_Logo.jpg) (r)'
Assuming you don't have a hard disk on your printer, you need to put the JPEG data into the PostScript program and use currentfile as the data source with a DCTDecode filter of course. You will need to learn how to use the image operator instead of colorimage and it would be better to use the dictionary form of the operator too.
You mention in the comments "I stored the image to the hard disk of the printer." But it would appear that the postscript interpreter cannot access it, or uses a different path, or even a different path naming convention. Using the bare filename will work with ghostscript or ghostview if launched from the same directory, so the running program has an environment variable CWD for current working directory. As an aside, it appears to be a clone interpreter, since it throws /undefined instead of /undefinedfilename.
Accessing a printer's disk from a postscript program is going to be very product-specific.
But the method Ken describes will bypass any of these problems.
Using currentfile as the data source means the image operator will read data directly from the postscript program file. So you need to embed the data directly into the program source code text. You can either use your text editor to read-in the file, or maybe some kind of macro-processor with inclusion capabilities.
A much easier way is to use ghostscript to produce a printable file. ps2pdf or ps2ps (possibly with -DNOSAFER) will process the program and distill the output.

Trouble generating Tabloid (11x17) pdf file from Postscript

I have a Postscript file that was intended to be printed on 11x17 paper. But under Mac OSX, the preview program insists on cropping it to letter size. If I actually print it to 11x17 paper, it gets cropped to letter size and then centered in the 11x17 sheet.
(Note that the preview program always converts to pdf as an intermediate step).
Clearly, the generated pdf file is a letter-sized pdf file. I'm guessing that my Postscript file is missing some sort of syntactical sugar to clue the pdf converter as to what the paper size is, but I'm at a loss. I've tried inserting %%DocumentMedia and %%BeginPaperSize comments into the document at what I take are the right locations, but no effect.
I also tried moving the document to a Linux system, running ps2pdf, and moving the resulting pdf file back to the Mac. No effect. And ps2pdf has never done me wrong before, so that's what makes me think that the problem lies in my Postscript rather than in Apple's pdf converter.
%!PS-Adobe-3.0
%%BoundingBox: 0 0 792 1224
%%Creator: template plugin by Edward Falk
%%DocumentMedia: Tabloid 792 1224 0 () ()
%%Pages: 1
%%PageOrder: Ascend
%%DocumentData: Clean7Bit
%%EndComments
%%BeginDefaults
%%PageMedia: Tabloid
%%EndDefaults
%%BeginProlog
/drawmarker { % x y --
gsave
translate
newpath
0 -0.5 moveto 0 0.5 lineto
-0.5 0 moveto 0.5 0 lineto
0 0 .25 0 360 arc
stroke
grestore
} bind def
/drawmodel {
newpath
86.250 35.750 moveto
80.536 45.500 lineto
86.250 35.750 moveto
103.000 35.750 lineto
80.536 45.500 moveto
103.000 45.500 lineto
103.000 35.750 lineto
stroke
} bind def
%%EndProlog
%%Page: "1" 1
gsave
72 72 scale
-79.54 -34.75 translate
1 72 div setlinewidth
drawmodel
80.54 35.75 drawmarker
89.54 35.75 drawmarker
80.54 50.75 drawmarker
89.54 50.75 drawmarker
grestore
showpage
%%EndPage: "1" 1
%%EOF
Your PostScript doesn't request a page size. Lines beginning '%' are comments in PostScript and don't have any effect (some PostScript consumers will parse DSC comments, which confuses the issue...)
If you want 11x17 media, you need to ask for it:
<</PageSize [792 1224]>> setpagedevice
Without that you get the default media, whatever that may be. Blank lines are permitted in PostScript and have no effect, a DSC parser which behaves differently with blank lines present is a broken parser, but as I understand it gv is really very old.
Well, I figured it out by reverse-engineering some other files (pdftops is your friend). Documenting my solution here for others who may have the same question in the future.
The missing element wasn't related to DSC, it was actually the setdevicepage operator. Adding this code fixed my problem:
%%BeginSetup
2 dict begin
/PageSize 792 1224 2 array astore def
/ImagingBBox null def
currentdict end setpagedevice
%%EndSetup
If course, doing it right requires testing to see if the setpagedevice function exists, as it was added in language level 2.
Update: simplified using language level 2 features:
%%BeginSetup
% set up for pdf
<< /PageSize [792 1224] /ImagingBBox null >> setpagedevice
%%EndSetup

Why Sobel operator looks that way?

For image derivative computation, Sobel operator looks this way:
[-1 0 1]
[-2 0 2]
[-1 0 1]
I don't quite understand 2 things about it,
1.Why the centre pixel is 0? Can't I just use an operator like below,
[-1 1]
[-1 1]
[-1 1]
2.Why the centre row is 2 times the other rows?
I googled my questions, didn't find any answer which can convince me. Please help me.
In computer vision, there's very often no perfect, universal way of doing something. Most often, we just try an operator, see its results and check whether they fit our needs. It's true for gradient computation too: Sobel operator is one of many ways of computing an image gradient, which has proved its usefulness in many usecases.
In fact, the simpler gradient operator we could think of is even simpler than the one you suggest above:
[-1 1]
Despite its simplicity, this operator has a first problem: when you use it, you compute the gradient between two positions and not at one position. If you apply it to 2 pixels (x,y) and (x+1,y), have you computed the gradient at position (x,y) or (x+1,y)? In fact, what you have computed is the gradient at position (x+0.5,y), and working with half pixels is not very handy. That's why we add a zero in the middle:
[-1 0 1]
Applying this one to pixels (x-1,y), (x,y) and (x+1,y) will clearly give you a gradient for the center pixel (x,y).
This one can also be seen as the convolution of two [-1 1] filters: [-1 1 0] that computes the gradient at position (x-0.5,y), at the left of the pixel, and [0 -1 1] that computes the gradient at the right of the pixel.
Now this filter still has another disadvantage: it's very sensitive to noise. That's why we decide not to apply it on a single row of pixels, but on 3 rows: this allows to get an average gradient on these 3 rows, that will soften possible noise:
[-1 0 1]
[-1 0 1]
[-1 0 1]
But this one tends to average things a little too much: when applied to one specific row, we lose much of what makes the detail of this specific row. To fix that, we want to give a little more weight to the center row, which will allow us to get rid of possible noise by taking into account what happens in the previous and next rows, but still keeping the specificity of that very row. That's what gives the Sobel filter:
[-1 0 1]
[-2 0 2]
[-1 0 1]
Tampering with the coefficients can lead to other gradient operators such as the Scharr operator, which gives just a little more weight to the center row:
[-3 0 3 ]
[-10 0 10]
[-3 0 3 ]
There are also mathematical reasons to this, such as the separability of these filters... but I prefer seeing it as an experimental discovery which proved to have interesting mathematical properties, as experiment is in my opinion at the heart of computer vision.
Only your imagination is the limit to create new ones, as long as it fits your needs...
EDIT The true reason that the Sobel operator looks that way can be be
found by reading an interesting article by Sobel himself. My
quick reading of this article indicates Sobel's idea was to get an
improved estimate of the gradient by averaging the horizontal,
vertical and diagonal central differences. Now when you break the
gradient into vertical and horizontal components, the diagonal central
differences are included in both, while the vertical and horizontal
central differences are only included in one. Two avoid double
counting the diagonals should therefore have half the weights of the
vertical and horizontal. The actual weights of 1 and 2 are just
convenient for fixed point arithmetic (and actually include a scale
factor of 16).
I agree with #mbrenon mostly, but there are a couple points too hard to make in a comment.
Firstly in computer vision, the "Most often, we just try an operator" approach just wastes time and gives poor results compared to what might have been achieved. (That said, I like to experiment too.)
It is true that a good reason to use [-1 0 1] is that it centres the derivative estimate at the pixel. But another good reason is that it is the central difference formula, and you can prove mathematically that it gives a lower error in its estmate of the true derivate than [-1 1].
[1 2 1] is used to filter noise as mbrenon, said. The reason these particular numbers work well is that they are an approximation of a Gaussian which is the only filter that does not introduce artifacts (although from Sobel's article, this seems to be coincidence). Now if you want to reduce noise and you are finding a horizontal derivative you want to filter in the vertical direction so as to least affect the derivate estimate. Convolving transpose([1 2 1]) with [-1 0 1] we get the Sobel operator. i.e.:
[1] [-1 0 1]
[2]*[-1 0 1] = [-2 0 2]
[1] [-1 0 1]
For 2D image you need a mask. Say this mask is:
[ a11 a12 a13;
a21 a22 a23;
a31 a32 a33 ]
Df_x (gradient along x) should be produced from Df_y (gradient along y) by a rotation of 90o, i.e. the mask should be:
[ a11 a12 a11;
a21 a22 a21;
a31 a32 a31 ]
Now if we want to subtract the signal in front of the middle pixel (thats what differentiation is in discrete - subtraction) we want to allocate same weights to both sides of subtraction, i.e. our mask becomes:
[ a11 a12 a11;
a21 a22 a21;
-a11 -a12 -a11 ]
Next, the sum of the weight should be zero, because when we have a smooth image (e.g. all 255s) we want to have a zero response, i.e. we get:
[ a11 a12 a11;
a21 -2a21 a21;
-a31 -a12 -a31 ]
In case of a smooth image we expect the differentiation along X-axis to produce zero, i.e.:
[ a11 a12 a11;
0 0 0;
-a31 -a12 -a31 ]
Finally if we normalize we get:
[ 1 A 1;
0 0 0;
-1 -A -1 ]
and you can set A to anything you want experimentally. A factor of 2 gives the original Sobel filter.

Resources