PostScript error with imagemask and raw data - ghostscript

In Adobe's PLRM
I found the following example using the imagemask operator.
This works fine when running with Ghostscript.
54 112 translate % Locate lower-left corner of square
120 120 scale % Scale 1 unit to 120 points
0 setgray % Set current color to black
24 23 % Specify dimensions of source mask
true % Set polarity to paint the 1 bits
[24 0 0 -23 0 23] % Map unit square to mask
{< 003B00 002700 002480 0E4940
114920 14B220 3CB650 75FE88
17FF8C 175F14 1C07E2 3803C4
703182 F8EDFC B2BBC2 BB6F84
31BFC2 18EA3C 0E3E00 07FC00
03F800 1E1800 1FF800 >}
imagemask
showpage
As an exercise I tried to rewrite the above example using an ImageType-1 dictionary and raw data, and finally came up with this code:
54 112 translate
120 120 scale
0 setgray
<<
/ImageType 1
/Width 24
/Heigth 23
/BitsPerComponent 1
/Decode [1 0]
/ImageMatrix [24 0 0 -23 0 23]
/DataSource currentfile /ASCIIHexDecode filter
>>
imagemask
003B00 002700 002480 0E4940
114920 14B220 3CB650 75FE88
17FF8C 175F14 1C07E2 3803C4
703182 F8EDFC B2BBC2 BB6F84
31BFC2 18EA3C 0E3E00 07FC00
03F800 1E1800 1FF800>
showpage
However, when running this with Ghostscript I get the following error.
Error: /undefined in --imagemask--
I'm still scratching my head to find the bug, but in vain.
How can it be imagemask is undefined? Or did I miss something obvious?

I don't know if this is exactly the code you've written, but there's a typo:
/Heigth 23
which should obviously be:
/Height 23
If I correct that, the file runs to completion, and draws the turkey.

Related

Edit (every page of a) Postscript file manually

I want to (manually) insert additional postscript commands in a postscript file that was converted from a PDF file via ghostscript’s pdf2ps. For the purpose of testing I created a PDF file from the following file using pdflatex:
\documentclass[a4paper]{article}
\begin{document}
Mostly empty.
\end{document}
In the converted postscript file I make the following edit:
...
%%Page: 1 1
%%PageBoundingBox: 0 0 595 841
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 595.28 841.89]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
/Font 8 0 R
>>
/Contents 5 0 R
>>
endobj
%%EndPageSetup
% BEGIN MANUAL EDIT
0 setgray 0 0 moveto 595 841 lineto stroke
% END MANUAL EDIT
5 0 obj
<</Length 257>>stream
q 0.1 0 0 0.1 0 0 cm
0 G
0 g
q
10 0 0 10 0 0 cm BT
/R6 9.9626 Tf
1 0 0 1 139.746 706.129 Tm
[(M)-0.699638(os)-0.399443(t)-0.900585(l)-0.798886(y)-333.819(e)-0.400668(m)-0.300195(p)-0.599165(t)26.0974(y)83.192(.)-0.800112]TJ
154.421 -615.691 Td
(1)Tj
ET
Q
Q
endstream
endobj
pagesave restore
%%PageTrailer
%%Trailer
end
%%EOF
Instead of producing a diagonal line the postscipt/PDF file remains (seemingly) unchanged. However, if I alter the page dimensions from A4 to letter size the line is shown:
%%Page: 1 1
%%PageBoundingBox: 0 0 612 792
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 612 792]
...
I am obviously missing something here (which is not surprising given my rudimentary knowledge of postscript). My question is: How can I make the line appear while keeping the page dimensions unchanged?
P.S.: A comment I stumbled across mentioned that pdftops (from poppler-utils) is in some sense superior to pdf2ps. Indeed, inserting commands into the converted postscript file immediately before the showpage command (which is not there at all when using pdf2ps) worked fine. So I have probably already found a solution to my problem. However, I would like to learn what the page dimensions have to do with it when using pdf2ps.
Solution
Thanks to KenS’s advice and referring to his answer to this question I was able to achieve the desired effect by adding an EndPage procedure to the postscript file:
<<
/EndPage
{
exch pop 2 lt
{
gsave
0 0 translate
0 setgray 0 0 moveto 596 842 lineto stroke
grestore
true
}{false} ifelse
} bind
>> setpagedevice
(This assumes the page size is a4.)
PostScript is a write-only language :-)
Seriously, its a programming language. In order to understand what's going on, you need to understand the program, which in the case of the output from Ghostscript's ps2write device, is distinctly non-trivial.
The syntax is basically PDF, with a prolog program which interprets it in PostScript terms.
The program will use showpage, it does it when the procedure EndStream is executed, which is (basically) when the endobj keyword is encoutnered in a page stream. You'll see that it looks like:
ET
Q
Q
Q
endstream
endobj
%%Page: 2 2
You could place anything you like between the endstream and the endobj, but you need to be aware that the graphics state at that point is determined by whatever operations have already taken place. This can include scaling, oration, skeing, flipping the vertical axis, etc. So simply inserting some PostScript into there is unlikely to work. You could do an initgraphics which would at least reset the graphics state to a known setup.
As a test I ran Ghostscript'sd ps2write device like this:
gs -sDEVICE=pdfwrite -o out.ps -c "showpage" -f
which produces a PostScript program where the (effective) content is:
%%EndResource
%%EndProlog
%%Page: 1 1
%%PageBoundingBox: 0 0 595 842
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 595 842]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
>>
/Contents 5 0 R
>>
endobj
%%EndPageSetup
5 0 obj
<</Length 23>>stream
q 0.1 0 0 0.1 0 0 cm
Q
endstream
endobj
%%Trailer
end
%%EOF
I then modified this more or less as you suggested:
%%EndPageSetup
0 setgray 0 0 moveto 595 842 lineto stroke
5 0 obj
<</Length 23>>stream
q 0.1 0 0 0.1 0 0 cm
Q
endstream
endobj
%%Trailer
For me this produced the expected stroke from bottom left to top right. Obviously without the PostScript file you originally produced I can't tell you why your experience is different. (no I'm not in a position to run latex to produce such a thing, and even if I did I have no way to know which version of Ghostscript and the other tools you used).
My guess would be that 'something' in your PDF file overwrote the entire page, its not entirely uncommon.

How do I write a DXF code for a POLYLINE?

Hello I´m trying to create a program based on C++ that calculates a function values on a given range and then the program proceeds to create a DXF file in order for it to be Graphed.
The issue that I´m having it´s with the DXF part this is the code that my C++ program generates but it seems to be unable to be read by Autocad. Any insights on the issue will be much appreciated.
0
SECTION
2
ENTITIES
0
POLYLINE
8
0
62
1
66
1
70
8
0
VERTEX
8
0
70
32
10
1
20
2
30
0
0
VERTEX
8
0
70
32
10
1.2
20
2.13688
30
0
0
VERTEX
8
0
70
32
10
1.4
20
2.28024
30
0
0
VERTEX
8
0
70
32
10
1.6
20
2.42929
30
0
0
VERTEX
8
0
70
32
10
1.8
20
2.58329
30
0
0
VERTEX
8
0
70
32
10
2
20
2.74166
30
0
0
91
0
0
SEQEND
0
ENDSEC
0
EOF
There is an error in the last VERTEX:
0
VERTEX
8
0
70
32
10
2
20
2.74166
30
0
0 <---- This 0 is too much, starts a structural group tag (0, 91)
91
0
0
SEQEND
0
ENDSEC
0
EOF
If you have any information what the group code 91 (vertex identifier) is for, let me know, I am very interested.
The Issue that I was seem to be having it´s that I was using the DXF codes for a LWPOLYLINE when I should be using the DXF regarding POLYLINE. The difference is subtle but if the person that´s reading this is having the issue backtrack one by one the GROUP CODES and make sure all of them are part of the same ENTITY. I will share the code that finally was able to create an OUTPUT on AutoCad 2018 (Keep in mind the changes on the DXF format on the versions of AutoCad depending on your case)
0
SECTION
2
ENTITIES
0
POLYLINE
8
0
62
1
66
1
70
8
0
VERTEX
8
0
70
32
10
0
20
0
30
0
0
SEQEND
0
ENDSEC
0
EOF

Iterate over a tensor's rows and cols in Tensorflow

A part of my project is to use a thresholding kernel on an image.
The thresholding kernel could look like this:
[50 100]
[150 200]
I would like to go over each group of 3x3 pixels (without overlap), and threshold them using my kernel.
For example, if I have this grayscale image:
[120 120 120 120]
[120 120 120 120]
[170 170 170 170]
[170 170 170 170]
Then after thresholding I should get this image:
[1 1 1 1]
[0 0 0 0]
[1 1 1 1]
[1 0 1 0]
I am using TensorFlow, and my network is needed with different shapes of batches.
The input is:
data['input_tensor'] = tf.placeholder(tf.float32, shape=[None, None, None, 1], name='Input')
The thresholding kernel is of type: tf.Variable(), and size 5x5,
AND ITS VALUES SHOULD BE LEARNED!
I can't find a way to make it happen.
I tried iterating through the input batch, but its size is unknown (it is only known during a session).
I don't want to duplicate the thresholding kernel, because then the network will try to learn all of its values (and it's too much for now).
Is there a way to do it without loops?
If not, how could I do it with loops?
Thanks.

PS easy way to color text

I have a postscript file that contains a phylogenetic tree outputted by njplot. It basically consists of lines and labels at the end of the line. Right now it is in black and white but I would like to mark differences between different trees:
Below is a short extract from one of my files with only three of the labels.
a) What do I have to do to make e.g. "B. ovis 25840" be displayed in red?
b) How can I make a box around "B. suis 23445" and "B. Thomsen" (such as to mark that they are in the same group?)
/setpacking where {true setpacking} if
1 setlinecap 1 setlinejoin 1 setlinewidth 0 setgray
/basefont /Times-Roman findfont 12 scalefont def
/titlefont /Times-Roman findfont 12 scalefont def
/setclip {40 40 moveto 560 40 lineto 560 810 lineto 40 810 lineto closepath clip newpath} def
/title {titlefont setfont
40 815 moveto (brucella_conc_se_ani.out_nj.outtree Mon Aug 14 14:52:28 2017
) show ( Page ) show show ( of 1) show
} def
%%EndProlog
%%Page: ? 1
(1) title setclip
0 0 translate
basefont setfont
50 50 translate
0.7 setgray -10 -10 moveto 510 -10 lineto 510 760 lineto -10 760 lineto closepath stroke 0 setgray
359 8 moveto
(B. ovis 25840) show
298 67 moveto
(B. Thomsen) show
294 127 moveto
(B. suis 23445) show
showpage
Text is drawn (for text in fonts other than type 3) using the current color. So if you alter the current color before drawing the text, then it will be drawn in a different color.
There are a number of color operators in PostScript, the simplest are the setgray, setrgbcolor and setcmykcolor operators. setgray takes a value between 1 (white) and 0 (black) and sets the current color to that percentage of gray. setrgbcolor takes 3 parameters between 01 and 1 for each of R, G and B, and setcmykcolor does the same but with CMYK components.
So to answer question 'a' 1 0 0 setrgbcolor placed before the line with the text on it, would cause the text to be drawn in red.
Note that all subsequent operations would also be rendered in red, so we should consider now the gsave and grestore operators. gsave saves a copy of the graphics state, and grestore (surprise!) restores the graphics state from the most recently saved version.
You can use this to limit the effect of a graphics state change. For example:
gsave
1 0 0 setrgbcolor
(B. ovis 25840) show
grestore
would render the text in red, but the subsequent text would be in the colour in force before the gsave, presumably black.
Note that the current point on the page is part of the gstate! So :
gsave
1 0 0 setrgbcolor
359 8 moveto
(B. ovis 25840) show
298 67 moveto
grestore
(B. Thomsen) show
would cause the second 'show' to take place at the same position as the first one, overwriting it.
You don't 'draw a box', PostScript doesn't have graphics primitives like that. What you do is construct a path, and then stroke it (you could fill it instead for a filled rectangle).
For example:
0 0 moveto
0 100 lineto
100 100 lineto
100 0 liento
closepath
stroke
will construct a rectangular path with its bottom left corner at 0,0 it will be 100 units wide and tall (so a square). The 'stroke' operator then strokes the path using the current linewidth and the current colour.
If you want to dig deeper into PostScript then you will need a copy of the PostScript Language Reference Manual, which is available online in PDF format from the Adobe web site.
You might also like to look at the the 'Blue Book' which is also available there as the 'PostScript language tutorial and cookbook'

Replacing selective numbers with NaNs

I have eight columns of data. Colulmns 1,3, 5 and 7 contain 3-digit numbers. Columns 2,4,6 and 8 contain 1s and zeros and correspond to 1, 3, 5 and 7 respectively. Where there is a zero in an even column I want to change the corresponding number to NaN. More simply, if it were
155 1 345 0
328 1 288 1
884 0 145 0
326 1 332 1
159 0 186 1
then 884 would be replaced with NaN, as would 159, 345 and 145 with the other numbers remaining the same. I need to use NaN to maintain the data in matrix form.
I know I could use
data(3,1)=Nan; data(5,1)=Nan
etc but this is very time consuming. Any suggestions would be very welcome.
Approach 1
a1 = [
155 1 345 0
328 1 288 1
884 0 145 0
326 1 332 1
159 0 186 1]
t1 = a1(:,[2:2:end])
data1 = a1(:,[1:2:end])
t1(t1==0)=NaN
t1(t1==1)=data1(t1==1)
a1(:,[1:2:end]) = t1
Output -
a1 =
155 1 NaN 0
328 1 288 1
NaN 0 NaN 0
326 1 332 1
NaN 0 186 1
Approach 2
[x1,y1] = find(~a1(:,[2:2:end]))
a1(sub2ind(size(a1),x1,2*y1-1)) = NaN
I would split the problem into two matrices, with one being a logical mask, the other holding your data.
data = your_mat(:,1:2:end);
valid = your_mat(:,2:2:end);
Then you can simply do:
data(~valid)=NaN;
You could then rebuild your data by doing:
your_mat(:,1:2:end) = data;
Here is an interesting solution, I would expect it to perform quite well, but be aware that it is a bit tricky!
data(~data(:,2:end))=NaN
Using logical indexing:
even = a1(:,2:2:end); % even columns
odd = a1(:,1:2:end); % odd columns
odd(even == 0) = NaN; % set odd columns to NaN if corresponding col is 0
a1(:,1:2:end) = odd; % assign back to a1
a1 =
155 1 NaN 0
328 1 288 1
NaN 0 NaN 0
326 1 332 1
NaN 0 186 1
Here is an alternative solution. You can use circshift, in the following manner.
First create a mask of the even columns of the same size of your input matrix A:
AM = false(size(A)); AM(:,2:2:end) = true;
Then circshift the mask (A==0)&AM one element to the left, to shift this mask on the odd columns.
A(circshift((A==0)&AM,[0 -1])) = nan;
NOTE: I've searched for a one-liner ... I don't think it's a good one, but here is one you can use, based on my solution:
A(circshift(bsxfun(#and, A==0, mod(0:size(A,2)-1,2)),[0 -1])) = nan;
The dirty thing with bsxfun is to create on-line the mask AM. I use for that the oddness test on a vector of indices, bsxfun extends it over the whole matrix A. You can do anything else to create this mask, of course.

Resources