Editing thickness in postscript (.ps or .eps) figures via unix shell commands? - shell

I have many figures (graphs) in postscript (.eps) format that I wish to thicken the plots with.
I found the following code, but the output file is no different. I was wondering what I was doing wrong.
The code:
# get list of all arguments
set args = ($*)
# if not enough arguments, complain.
if ($#args < 2) then
echo "Usage: ps_thicken ps_file factor"
echo "Thickens all lines in a PostScript file by changing the linewidth macro."
echo "Result goes to standard output."
exit 1
endif
sed -e "s/^\/lw {\(.*\) div setlinewidth/\/lw {$2 mul \1 div setlinewidth/" $1
Now to execute this from my command line, I use the command (filename is ps_thicken, and has appropriate permissions):
./ps_thicken old_file.eps 10 > new_thick_file.eps
Which I thought should make everything 10x thicker, but it just doesnt change anything.
Any help would be greatly appreciated, I'm pretty new to shell script!

PostScript is a programming language, so it isn't really possible to make changes in an automated fashion like this. At least not without writing a PostScript program to do so!
Note that linewidth isn't a 'macro' (PostScript doesn't have macros) its am operator. What the code you've posted for sed does (if I recall sed well enough) is look for the definition of /lw and replace it with a modified version. The problem with that is that /lw is a function declartation in a particular PostScript program. Most PostScript programs won't have (or use) a function called 'lw'.
You would be much better to prepend the PostScript program code with something like:
/oldsetlinewidth /linewidth load def
/setlinewidth {2 div oldsetlinewidth} bind def
That will define (in the current dictionary) a function called 'setlinewidth'. Now, if the following program simply uses the current definition of setlinewdith when creating its own functions, it will use the redefined one above. Which will have the effect of dividing all line widths by 2 in this case. Obviously to increase the width you would use something like 2 mul instead of 2 div.
Note that this is by no means foolproof, its entirely possible for a PostScript program to explicitly load the definition of setlinewidth from systemdict, and you can't replace that (at least not easily) because systemdict is read-only.
However its unlikely that an EPS program would pull such tricks, so that should probably work well enough for you.
[based on comments]
Hmm, you mean 'failed to import' into an application or something else ?
If you're loading the EPS into an application then simply putting that code in front of it will break it. EPS (unlike PostScript) is required to follow some rules, so to modify it successfully you will have to follow them. This includes skipping over any EPS preview.
This is not really a trivial exercise. Your best bet is probably to run the files through Ghostscript, you can do a lot by harnessing a PostScript interpreter to do the work.
Start with the 2 lines of PostScript above in a file, then run the EPS file you want to 'modify' through Ghostscript, using the eps2write device. That will produce a new EPS which has the changes 'baked in'.
Eg (assuming the linewidth modifying code is in 'lw.ps'):
gs -sDEVICE=eps2write -o out.eps lw.ps file.eps
But be aware that the resulting EPS is a completely rewritten program and will bear no relation to the original. In particular any preview thumbnail will be lost.

Related

What is wrong with this PDF file?

I have to work with a PDF form created by a person unknown to me. Why did the program with which the form was created (Word + PDF export?) split the term "Stunde" into "S", "t" and "unde" in line 6909 of the decoded PDF? There is no visual break between the three parts.
/TT1 1 Tf
11.04 0 0 11.04 59.16 476.1203 Tm
(Datum)Tj
/C2_1 1 Tf
<0003>Tj
/TT1 1 Tf
(der)Tj
0.424 -1.315 Td
(Tätigkeit)Tj
-0.0022 Tc 0 11.04 -11.04 0 261.24 437.7203 Tm
[(Ve)-4.6<7267fc74>-4.2(ungssat)-4.2(z)]TJ
/C2_1 1 Tf
0 Tc <0003>Tj
/TT1 1 Tf
-0.0021 Tc 0.935 -1.315 Td
[<2880>-6.1(/)-7.2(S)0.8(t)-4.1(unde)-4.5(\))]TJ % <<< the important line
0 Tc 11.04 0 0 11.04 340.92 468.8003 Tm
(Anlass/Art)Tj
/C2_1 1 Tf
resulting in
[]
To get the source code above, I decoded the PDF file as described here. I have no know-how concerning the PDF file format.
Background: I had to replace the word "Stunde", it drove me crazy to find the place where "Stunde" was written (in parts) within the source code, since no free PDF editor seems to be able to work with horizontal text without problems.
Academic Bonus questions: Is it possible to set the sum over a column as default value for a form field? (Modifiable; changed every time the column is changed.) Why was I able to replace "Stunde" with "Einsatz" without making the PDF file corrupt due to now irregular offsets?
Why did the program with which the form was created (Word + PDF export?) split the term "Stunde" into "S", "t" and "unde" in line 6909 of the decoded PDF?
As #gettalong mentioned in his answer, in your case this most likely has been done to apply kerning.
If you start looking into the outputs of some other PDF producers, you'll see that this export from Word actually is very unobtrusive in regard to splitting words:
there are PDF producers that draw each character individually after explicitly setting the text matrix for it, and
there also are PDF producers that have the width information for the characters of the used fonts set to zero and use the numbers in TJ instructions to forward the current text matrix between characters accordingly.
And this doesn't cover all the variants to be found, not by far...
Thus,
I had to replace the word "Stunde", it drove me crazy to find the place where "Stunde" was written (in parts) within the source code
in your case replacing actually was a fairly trivial task...
Is it possible to set the sum over a column as default value for a form field? (Modifiable; changed every time the column is changed.)
If all the column values in question are stored in form fields, you can use JavaScript to recalculate sums after form changes. To have it serve as "default" only, you can use some other (hidden) field for a flag whether the field has already been touched. Beware, though: JavaScript is not supported by all PDF viewers. Furthermore, the JavaScript object model for PDF is not specified in an independent (like ISO) specification but in an Adobe one which can make interpretation of the specification biased.
Why was I able to replace "Stunde" with "Einsatz" without making the PDF file corrupt due to now irregular offsets?
As we don't know how exactly you applied the changes, this obviously is hard to tell.
Most likely, though, you did corrupt the PDF and the PDF viewers you opened it in merely repair the corruption under the hood. There is a strong tendency in PDF viewers to do such under-the-hood repairs without informing the user; the result is that a large part of the PDFs in the wild actually being broken.
You don't see a visual break but the standard distance between "S", "t" and "unde" has been changed nonetheless. This is done by PDF writers that support e.g. kerning so that the word appear nicer. This is the reason why it is split that way.

Convert PDF files to PDF/A via Ghostscript

I'd like to convert arbitrary PDF files to PDF/A with Ghostscript 9.15.
Is Ghostscript able to create PDF/A-3b conformant PDFs? There is no parameter which represents a PDF/A conformance level, so I assume there is no possibility. Or is there anything I have overlooked?
I was following a blog post where a Windows batch file is used to convert from PDF to PDF/A (see http://www.mcbsys.com/techblog/2013/04/batch-convert-pdf-to-pdfa/). The gs invokation in the batch is:
"%gs_path%\gswin64c" ^
-dPDFA ^
-dNOOUTERSAVE ^
-sProcessColorModel=DeviceRGB ^
-sDEVICE=pdfwrite ^
-o "GS_%file1%" ^
-dPDFACompatibilityPolicy=1 ^
"%currentdir%\PDFA_def.ps" ^
%inputfilelist%
The PDFA_def.ps is an adjusted version of the official one:
%!
% This prefix file for creating a PDF/A document is derived from
% the sample included with Ghostscript 9.07, released under the
% GNU Affero General Public License.
% Modified 4/15/2013 by MCB Systems.
% Feel free to modify entries marked with "Customize".
% This assumes an ICC profile to reside in the file (AdobeRGB1998.icc),
% unless the user modifies the corresponding line below.
% The color space described by the ICC profile must correspond to the
% ProcessColorModel specified when using this prefix file (GRAY with
% DeviceGray, RGB with DeviceRGB, and CMYK with DeviceCMYK).
% Define entries in the document Info dictionary :
/ICCProfile (... PATH TO ... AdobeRGB1998.icc) % Customize.
def
[ /Title (Title) % Customize.
/DOCINFO pdfmark
% Define an ICC profile :
[/_objdef {icc_PDFA} /type /stream /OBJ pdfmark
[{icc_PDFA} <</N systemdict /ProcessColorModel get /DeviceGray eq {1} {systemdict /ProcessColorModel get /DeviceRGB eq {3} {4} ifelse} ifelse >> /PUT pdfmark
[{icc_PDFA} ICCProfile (r) file /PUT pdfmark
% Define the output intent dictionary :
[/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark
[{OutputIntent_PDFA} <<
/Type /OutputIntent % Must be so (the standard requires).
/S /GTS_PDFA1 % Must be so (the standard requires).
/DestOutputProfile {icc_PDFA} % Must be so (see above).
/OutputConditionIdentifier (AdobeRGB1998) % Customize
>> /PUT pdfmark
[{Catalog} <</OutputIntents [ {OutputIntent_PDFA} ]>> /PUT pdfmark
So, I use AdobeRGB1998.icc which is obviously useable for PDF files with RGB color space. Depending on the -sProcessColorModel value (DEVICERGB) a correct value is printed out.
The conversion works for all files. But when I validate the created PDF file against PDF/A-1b, I get different results depending whether the input file has RGB color space or not (e.g. CMYK). So, when I have an input PDF file which uses CMYK color space, the file gets converted by the script, but the validator says something like this:
input.pdf", 1, 38, 0x03418614, "A device-specific color space (DeviceCMYK) without an appropriate output intent is used.", 1
"output.pdf", 20, 0, 0x83410612, "The document does not conform to the requested standard.", 1
My question: Is there a way to get the conversion done for arbitrary files (i.e. independent of the used color space in the input file)?
Update
#KenS Thanks for your answer. I've updated my initial post to clarify what I want to achieve.
To make it more explicit, I will use an example. There are two files: input1.pdf (seems to use RGB) and input2.pdf (seems to use CMYK). I want to convert both of them to PDF/A-1. Thanks to your hint, I've let go of the above mentioned batch script and instead tested the command directly in the command line. After reading Ps2pdf.htm#PDFA, I have adjusted the (official) PDFA_def.ps so that AdobeRGB1998.icc is used. Then I invoked the following command on both input files (replaced output1.pdf by output2.pdf and input1.pdf by input2.pdf for the second file):
gswin64c.exe -dPDFA=1 -dBATCH -dNOPAUSE -dNOOUTERSAVE \
-sColorConversionStrategy=/RGB \
-sOutputICCProfile=AdobeRGB1998.icc -sDEVICE=pdfwrite \
-sOutputFile=output1.pdf -dPDFACompatibilityPolicy=1 \
"PATH/TO/OFFICIAL/PDFA_def.ps" input1.pdf
The conversion was done without any errors. The output1.pdf seems to be valid, but the output2.pdf is still invalid (tested with 3heights Validator):
"output2.pdf", 1, 40, 0x03418614, "A device-specific color space (DeviceCMYK) without an appropriate output intent is used.", 1
"output2.pdf", 20, 0, 0x83410612, "The document does not conform to the requested standard.", 1
So when I understand your answer correctly, the above command should produce a pdf file which uses the RGB color space - independent of the color space of the input file. If the input file uses CMYK, than the colors have to be translated into RGB with the above command.
When I interpret the first error message correctly, the used color space in the output2.pdf is still CMYK (although the command parameters like ColorConversionStrategy=/RGB). Since I used AdobeRGB1998.icc, the validation error appears.
What am I missing in the above command?
Going back to my original question (which is one step further): Instead of always converting to RGB (or CMYK), I wanted to somehow detect which color space is used in the input file and then dynamically switch to a RGB or CMYK icc file. Is it possible to achieve that?
Ghostscript does not support PDF/A-3. The conformance parameter you are looking for is -dPDFA= where valid values are nothing (defaults to 1), 1 or 2. You can find this documented in ghostpdl/gs/doc/ps2pdf/htm#PDFA
I'm not sure what you are asking for here though. You must either create a PDF/A file (in level 1 or 2 anyway, I haven't read the revision 3 spec yet) which is RGB or CMYK, because you aren't allowed to use both (you can convert everything to device independent colour of course). The colour space used in the input isn't relevant, other than to decide whether it needs to be converted.
This is something you need to decide, we can't decide it for you. One important reason is that the OutputIntent must be consistent with either RGB or CMYK, and the pdfwrite device doesn't check it, it assumes you chose one which matches the device space you are using for the PDF file (by the way, don't set the ProcessColorModel, use ColorConversionStrategy instead) In your case you have set OutputIntent to AdobeRGB1988 so your colours must be specified either in device independent colour, or RGB.
Given the errors you quote, I would suggest the problem is that you haven't specified -sColorConversionStrategy, so the input colours are not being converted to the required device space. I would further guess that the script you copied this from set -dUseCIEColor, and you didn't copy that bit. DO NOT set -dUseCIEColor, its a horrbile ancient piece of PostScript hackery. Instead set ColorConversionStrategy, which will convert colours in a much better way, as required.
Updated answer as this started getting too long for a comment:
I can't immediately see any problems with your command line, can you share an example PDF file ? Its much easier to investigate these things with a solid example. I know from our customers and other free users that pdfwrite is capable of producing conforming PDF/A-1b files.
Regarding the second question; its not possible to do that because currently you need to set the OutputIntentProfile to either a CMYK one or an RGB one before you start. You can't just run through the input PDF file until you come to a colour operation and then decide. If you feel like some programming it could be done by modifying pdfwrite, because the profile isn't actually used till the output is closed.
One problem is that, in order to do the colour conversion, you need to set the underlying ProcessColorModel (this is done for you automatically by ColorConversionStategy). The only way to change ProcessColorModel is to execute a setpagedevice, which causes an erasepage. Now I think that's actually fixable with pdfwrite, all it does is write a white rectangle over the page, so you should be able to intercept that and not emit it. Otherwise any marks you made before you encountered an RGB or CMYK operation would be underneath the white rectangle.....
So essentially no, you can't do it right now, if its important to you then you could probably modify the code to do so (don't forget you will also need to supply 2 OutputIntent profiles to choose between as well). We've never had a customer request to do this, so we won't likely take it on as a project. Of course if you did get this working we might very well incorporate it into the code base if you were to offer it back to us.

Montage using PythonMagick in Python 3?

I was hoping to be able to generate montages using PythonMagick. The documentation seems very sparse, but I've been trying to hunt it down using the code completion part of Eclipse at least, as well as a few other questions' suggestions here on Stack Overflow. It seems that the MagickWand API has the function I am looking for, according to this:
http://www.imagemagick.org/api/MagickWand/montage_8c.html
However, I cannot seem to find it in PythonMagick. Is this simply unavailable? If so I might just ditch the rest of my PythonMagick code and rely on subprocess.call on a portable ImageMagick distribution or something like that (this program will have to be portable, and run on Windows with an easy port to Mac OS... so far I have a few other PythonMagick commands working so I'd like to keep this route going if possible).
Thanks!
Using the python imagemagick/graphicsmagick bindings helps a lot, but unfortunately not all of the functionality is there yet. I actually had the same problem with #FizxMike. I needed to use montage and then do some further operations, but saving the file on hard disk and then reloading it in a proper pgmagick object in order to do the rest of the operations and saving it again was slow.
Eventually I used the subprocess solution, but instead of saving in a file, I redirect the output in stdout. Then, I use the stdout to load the image from a pgmagick.Blob in a pgmagick.Image object and do the rest of the processing in python code.
The procedure looks like this in code:
import os
import pgmagick
import subprocess
my_files = []
# Dir with the images that you want to operate on
dir_with_images = "."
for file in os.listdir(dir_with_images):
if file.endswith(".png"):
my_files.append(os.path.join(dir_with_images, file))
montage_cmd = ['gm', 'montage']
montage_cmd.extend(my_files)
# The trick is in the next line of code. Instead of saving in a file, e.g. myimage.png
# the montaged file will just be "printed" in the stdout with 'png:-'
montage_cmd.extend(['-tile', '2x2', '-background', 'none', '-geometry', '+0+0', 'png:-'])
# Use the command line 'gm montage' since there are not python bindings for it :(
p = subprocess.Popen(montage_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Get the stdout in a variable
stdout, stderr = p.communicate()
# Load the stdout in a python pgmagick Image object using the pgmagick.Blob
# and do the rest of the editing on python code
img = pgmagick.Image(pgmagick.Blob(stdout))
# Display the image
img.display()
geometry = pgmagick.Geometry(300, 200)
geometry.aspect(True)
# Resize the montaged image to 300x200, but keep the aspect ratio
img.scale(geometry)
# Display it again
img.display()
# And finally save it <- Only once disk access at this point.
img.write('myimage.png')
I have the same problem, even pgmagick lacks the montageImage() function needed (Magick++ montage example)
This is what I do (in a Django View):
#ImageMagick CLI is better documented anyway (-background none preserves transparency)
subprocess.call("montage -border 0 -geometry "+str(cols)+"x -tile 1x"+str(len(pages))+" "+target_path[0:len(target_path)-4]+"[0-9]*.png -background none "+target_path,shell=True)`
Not fun because I have to juggle around a bunch of files first... writing to hard disk is not the fastest thing to do, then delete the temp files.
I would much rather do it all in ram.
I am still in search of a better answer myself.

Convert a .rtf into a mac .r resource, in a scriptable way

I currently have a SLA in a .rtf format, which is to be integrated into .dmg using the intermediary .r mac resource format, which is used by the Rez utility. I had already done it by hand once, but updates made to the .rtf file are overwhelming to propagate to the disk image, and error-prone. I would like to automate this task, which could also help adding other languages or variants.
How could the process of .rtf to .r text conversion be automated?
Thanks.
Only because I didn't fully understand how the accepted answer actually achieved the goal, I use a combination of a script to generate the hex encoding:
#!/usr/bin/env ruby
# Makes resource (.r) text from binaries.
def usage
puts "usage: #{$0} infile"
puts ""
puts " infile The file to convert (the output will go to stdout)"
exit 1
end
infile = ARGV[0] || usage
data = File.read(infile)
data.bytes.each_slice(16) do |slice|
hex = slice.each_slice(2).map { |pair| pair.pack('C*').unpack('H*')[0] }.join(' ')
# We could put the comments in too, but it probably isn't a big deal.
puts "\t$\"#{hex}\""
end
The output of this is inserted into a variable during the build and then the variable ends up in a template (we're using Ant to do this, but the specifics aren't particularly interesting):
data 'RTF ' (5000, "English SLA") {
#english.licence#
};
The one bit of this which did take quite a while to figure out is that 'RTF ' can be used for the resource directly. The Apple docs say to separately insert 'TEXT' (with just the plain text) and 'styl' (with just the style). There are tools to do this of course, but it was one more tool to run and I could never figure out how to make hyperlinks work in the resulting DMG. With 'RTF ', hyperlinks just work.
Hoping that this saves someone time in the future.
Use the unrtf port (from macports), then format the lines, heading and tail with a shell script.

I get this window while editing Ruby Files in Vim. What is it?

I usually get this new window open up suddenly while I am editing a Ruby file in VIM. This is getting irritating because, i cant type in anything while its processing. And it usually happens arbitarily. Does any one here know which plugin could be doing this? Or is this somekind of VIM's process?
This is happening when you hit K in normal mode.
K Run a program to lookup the keyword under the
cursor. The name of the program is given with the
'keywordprg' (kp) option (default is "man"). The
keyword is formed of letters, numbers and the
characters in 'iskeyword'. The keyword under or
right of the cursor is used. The same can be done
with the command >
:!{program} {keyword}
There is an example of a program to use in the tools
directory of Vim. It is called 'ref' and does a
simple spelling check.
Special cases:
- If 'keywordprg' is empty, the ":help" command is
used. It's a good idea to include more characters
in 'iskeyword' then, to be able to find more help.
- When 'keywordprg' is equal to "man", a count before
"K" is inserted after the "man" command and before
the keyword. For example, using "2K" while the
cursor is on "mkdir", results in: >
!man 2 mkdir
- When 'keywordprg' is equal to "man -s", a count
before "K" is inserted after the "-s". If there is
no count, the "-s" is removed.
{not in Vi}
If you notice, it's running ri in the open window, which is the ruby documentation app.
In Unixy environments, the help program normally runs inline, just displacing the vim output for a minute.
Is this using gvim, or command-line vim?
In either case, you can try monkeying with 'keywordprg' to fix the popup
Or, if you can't train yourself not to type it, you can just use :nnoremap K k to change what K does (in this case, just treat it as normal k command and go up one line).
I have this same issue on my work desktop, but not my home machine. The setups are near identical.
While stalking down a possible cause, I noticed that when I leave my cursor over a Ruby symbol such as File, Vim would popup a short description of the File class. After comparing all the various vim scripts and ri-related files that I could find, I finally settled on the only solution that worked...
Open $HOME/_vimrc and add the following line:
autocmd FileType ruby,eruby set noballooneval
Previously, I commented out a block in $VIMRUNTIME/ftplugin/ruby.vim, but Brian Carper suggested a better solution of :set noballooneval. I added the autocmd line so it is only executed with Ruby files.
If anyone figures out a true solution, please contact me. :(

Resources