I would like to open a PDF in Photoshop using Python. I know how to open photoshop (.psd) files using python, but I am wondering if there is a way to specify the program used to open a file.
So far, all I do to open a photoshop document is:
psd = "path\to\photoshop\document"
os.startfile(psd)
but when I use os.startfile on a PDF it opens with Adobe Acrobat. I'd like to open the PDF in photoshop instead. Any ideas?
from comtypes.client import GetActiveObject
# Start up Photoshop application
# app = Dispatch('Photoshop.Application')
# Or get Reference to already running Photoshop application instance
app = GetActiveObject("Photoshop.Application")
fileName = "C:\Git\PS_Samples_Files\MyPDFFile.pdf"
docRef = app.Open(fileName)
More examples at https://github.com/lohriialo/photoshop-scripting-python
os.startfile just starts the specified file with its default application. Changing the default application for PDFs to photoshop would get the result you want, but at the cost of making opening PDFs in other circumstances really annoying.
To do this properly you'd need to script it using photshop's COM interface. I haven't tried that but this tutorial looks like if might fit your needs.
Photoshop has options in opening a PDF document, called Photoshop.PDFOpenOptions
You need win32com to dispatch the photoshop application. See sample code below
import win32com.client
import os, glob
folderin = r'D:\in'
if (__name__ == '__main__'):
psApp = win32com.client.Dispatch('Photoshop.Application')
for infile in glob.glob(os.path.join(folderin, '*.pdf')):
options = win32com.client.Dispatch('Photoshop.PDFOpenOptions')
options.CropPage = 0 # BoundingBox
options.Resolution = 300 # Pixels
options.Mode = 1 # Grayscale
options.BitsPerChannel = 8 # 8 bits per channel
options.AntiAlias = True
options.ConstrainProportions = True #Deprecated for Adobe Photoshop CS3
doc = psApp.Open(infile, options)
doc.flatten
doc.Trim(1)
doc.Close(2)
psApp.Quit()
Related
I’m using rhino.compute to calculate a mesh.
How could I convert the 3dm decoded mesh to an STL file?
Currently, I can only save it as a 3dm:
import compute_rhino3d.Grasshopper as gh
import rhino3dm
output = gh.EvaluateDefinition(definition_path, trees)
mesh = output['values'][0]['InnerTree']['{0}'][0]["data"]
mesh = rhino3dm.CommonObject.Decode(json.loads(mesh))
doc = rhino3dm.File3dm()
doc.Objects.AddMesh(mesh)
doc.Write("model.3dm", version=0)
Thank you very much!
You can use Rhino.RhinoDoc.WriteFile to write to all file types that rhino conventionally supports for exporting.
def ExportStl():
#Path to save File.
filepath = r"C:\Temp\TestExport.stl"
#Create write options to specify file info.
write_options = Rhino.FileIO.FileWriteOptions()
#Export all geometry, not just selected geometry.
write_options.WriteSelectedObjectsOnly = False
#Write File.
result = Rhino.RhinoDoc.ActiveDoc.WriteFile(filepath, write_options)
ExportStl()
In this case, I'm using the Rhino 'RunPythonScript' command with the open ActiveDoc but in your example, you could use doc.WriteFile(filepath, write_options) instead.
When you first run this, there is a .stl export dialogue that has export options. This window can be suppressed to the command line with write_options.SuppressDialogBoxes = True.
Or you can check the 'Always use these settings. Do not show this dialogue again.' option and it will not interrupt export in the future.
Your example suggests you may be working in a headless environment so I'm not sure how these dialogues would be handled in that scenario.
I have a chart function that saves the end figure as a file. After I run the function, I also want it to display the figure at the end. So, I use this:
from PIL import Image
filepath = 'image.png'
img = Image.open(filepath)
img.show()
It works just fine, but when the file opens, it opens with a random file name, not the actual file name.
This can get troublesome as I have a lot of different chart functions that work in a similar fashion, so having logical names is a plus.
Is there a way I can open an image file with Python and have it display it's original file name?
EDIT
I'm using Windows, btw.
EDIT2
Updated the example with code that shows the same behaviour.
Instead of PIL you could use this:-
import os
filepath = "path"
os.startfile(filepath)
Using this method will open the file using system editor.
Or with PIL,
import Tkinter as tk
from PIL import Image, ImageTk # Place this at the end (to avoid any conflicts/errors)
window = tk.Tk()
#window.geometry("500x500") # (optional)
imagefile = {path_to_your_image_file}
img = ImageTk.PhotoImage(Image.open(imagefile))
lbl = tk.Label(window, image = img).pack()
window.mainloop()
The function img.show() opens a Windows utility to display the image. The image is first written to a temporary file before it is displayed. Here is the section from the PIL docs.
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.show
Image.show(title=None, command=None)[source] Displays this image. This
method is mainly intended for debugging purposes.
This method calls PIL.ImageShow.show() internally. You can use
PIL.ImageShow.register() to override its default behaviour.
The image is first saved to a temporary file. By default, it will be
in PNG format.
On Unix, the image is then opened using the display, eog or xv
utility, depending on which one can be found.
On macOS, the image is opened with the native Preview application.
On Windows, the image is opened with the standard PNG display utility.
Parameters title – Optional title to use for the image window, where
possible.
"
The issue is that PIL uses a quick-and-dirty method for showing your image, and it's not intended for serious application use.
In photoshop and using python, I cannot save the active document as PSB (Large Document Format) file
With win32com.client, I can save active documents as .psd files like this:
from win32com.client import Dispatch
psApp = Dispatch("Photoshop.Application")
activeDocument = psApp.Application.ActiveDocument
activeDocument.SaveAs("E:\\PSDCopy", PhotoshopSaveOptions, False)
Though I cannot force it to save as psb no matter what I tried.
I also could not find any clue in the VBScript documentation, now even a word about psb files.
Any help would be deeply appreciated.
Adobe created a terrible API for interfacing with Photoshop. Worse than that, the documentation is deprecated and doesn't include updates like PSB files, EXR files etc.
A good way to find out how to write code for that is to use the Photoshop ActionListener and hack your way around (doesn't always work but it gives you some good leads). You can read more about it here.
This should do what you are looking:
import comtypes.client as ct
app = ct.CreateObject('Photoshop.Application')
def save_as_psb(path):
""" Save the current Document as PSB with maximised compatibility
turned ON.
Args:
path (str): This is the filename of the output PSB
"""
desc19 = ct.CreateObject("Photoshop.ActionDescriptor")
desc20 = ct.CreateObject("Photoshop.ActionDescriptor")
desc20.putBoolean(app.StringIDToTypeID('maximizeCompatibility'), True)
desc19.putObject(
app.CharIDToTypeID('As '), app.CharIDToTypeID('Pht8'), desc20)
desc19.putPath(app.CharIDToTypeID('In '), path)
logging.debug(path)
desc19.putBoolean(app.CharIDToTypeID('LwCs'), True)
app.executeAction(app.CharIDToTypeID('save'), desc19, 3)
I want to programmatically (using Python) split a multi-page tiff into single pages using Adobe Acrobat's exposed COM Objects.
I am writing this in order to answer my own question in order to put a viable answer out there, as I did not find anyone doing this on SO or any other forum.
Please, let me know what you think about my solution and feel free to leave your way of doing this.
Here is one way:
from win32com.client import Dispatch
def acrobat_split(f_path,f_name,f_ext):
# Connect to Adobe Acrobat.
avDoc = Dispatch("AcroExch.AVDoc")
# Open the input file (as a pdf).
src = f_path+'\\'+f_name+f_ext
avDoc.Open(src,src)
pdDoc = avDoc.GetPDDoc()
page_ct = pdDoc.GetNumPages()
# Set dst.
dst = f_path+'\\'+f_name+PAGE_DIV+".tif"
jsObject = pdDoc.getJSObject()
#Here you can save as many other types by using, for instance: "com.adobe.acrobat.xml"
jsObject.saveAs(dst,"com.adobe.acrobat.tiff")
pdDoc.Close()
del pdDoc
I am receiving an form upload with a Word docx document. I got all the parsing done successfully. I have to then display that Word document on the web.
The problem I am running into at this moment is that I have embedded EMF files (that the PIL library recognizes as WMF format), and I cannot figure how to convert them to something that can be displayed on the web (arbitrarily chosen PNG).
The code is somewhat simple:
im = PIL.Image.open(StringIO.StringIO(data))
fmt = im.format
if (fmt == 'WMF'):
fmt = 'PNG'
output = StringIO.StringIO()
im.save(output, format=fmt)
data = output.getvalue()
output.close()
return '''<img src="data:image/{0};base64,{1}" />'''.format(fmt, base64.encodestring(data))
The error i get is:
IOError: cannot find loader for this WMF file
These Word documents come from average user that may just have cut-and-paste images from the web or insert from file.
Is there a solution for me on a linux system?
Thanks.
EDIT:
To my defense, I tried to upload that document to google drive and the image is not displayed either. Maybe there are no simple solutions?
pip install Pillow
from PIL import Image
Image.open("xxx.wmf").save("xxx.png")
I found it easier to use the Wand package for such conversion. I tried the previous suggestions without success. So here is what I did:
(BTW, I wanted to convert all '.wmf' files into pdf)
import os
from wand.image import Image as wima
folder='C:/Users/PythonLover/Pictures/pics'
for oldfilename in os.listdir(folder):
if oldfilename.endswith(".wmf"):
with wima(filename=folder+'/'+oldfilename) as img:
newfilename = oldfilename.split('.')[0]+'.pdf'
newfilename = folder+'/'+newfilename
img.format = 'pdf'
img.save(filename=newfilename)
You need to understand what you are dealing with in order to see why what you are attempting to do is problematic. WMF files (or the more recent EMF and EMF+ formats) require Windows GDI to render the image it describes. So there is no simple solution when you are converting this format outside of Windows, since you need to replicate the GDI API.
One solution is to use the unoconv tool which relies on the UNO bindings for OpenOffice/LibreOffice. A second solution would use the pyemf module to decode the input, and then a second tool (to be done by you) would render it.
You may use libwmf to convert image to SVG and then pyrsvg to convert to PNG (described in another question).
I haven't found libwmf project website, but Debian (and Ubuntu) has package libwmf-bin that contains wmf2svg utility.
WMF stands for Windows Metafile; EMF stands for Enhanced Metafile. These files drive Windows to display an image. Within Microsoft Office applications it is a standard format for vector images. The Metafile is managed by Microsoft and is not an open format.
Since libreoffice is an alternative to Microsoft Office in Linux environment, it would be better to have a small service where we can use libreoffice and imagemagick(install them if you cannot).
Then a language independent solution would be this:
build a libreoffice container using this Dockerfile(or install libreoffice)
FROM linuxserver/libreoffice:7.2.2
start a RESTful API(or RPC API) in the container receiving an emf file and sending back a png file
in the service we implement the following function:
a. save the emf file in a path, say /mnt/b.emf
b. convert the file by the command libreoffice --headless --convert-to png /mnt/b.emf in any language; for example, in Python we can use the snippet at the end of this answer.
c. read the png file /mnt/b.png and send it back via the API
use imagemagick to trim the white space of the resultant image
Here is the Python implementation:
from os
from flask import Flask, jsonify, request
def emf_to_png(im):
temp_emf_path = '/tmp/temp.emf'
temp_png_path = '/tmp/temp.png'
with open(temp_emf_path, 'wb') as f:
f.write(im)
command = f"libreoffice --headless --convert-to png {temp_emf_path} --outdir /tmp"
os.system(command)
command = f'convert {temp_png_path} -fuzz 1% -trim +repage {temp_png_path}'
os.system(command)
f = open(temp_png_path, 'rb')
png_b = f.read()
f.close()
os.remove(temp_emf_path)
os.remove(temp_png_path)
return png_b
app = Flask(__name__)
#app.route("/convert/emf2png", methods=["POST"])
def start_training():
try:
emf = request.data
png_b = emf_to_png(emf)
return jsonify(code=200, message="succeed", data=png_b)
except Exception as e:
return jsonify(code=100, message=f"error {e}")
if __name__ == '__main__':
app.run("0.0.0.0", port=1111)
References:
https://stackoverflow.com/a/28749719/3552975
https://ask.libreoffice.org/t/convert-to-jpg-wmf-on-linux-resolution-issue/44578
I have a similar problem, but I used bash and inkscape to convert the images to png format, I attach the small script that performs this task for me:
#!/usr/bin/bash
for file in *.emf; do
export_name=$(echo $file | sed 's/\.emf$/.png/');
echo inkscape $file -e $export_name
inkscape $file -e $export_name
done
For more information, check the inkscape option:
inkscape --help
# -e, --export-png=FILE NAME
On linux you can use inkscape to do the conversion from .emf to .png with the help of command (pip install Command)
I also tried pillow and wand before, they both only works on windows.
import command
path_emf = 'path_to_your_emf_file'
path_png = 'path_to_save_png_file'
command.run(['inkscape', '-e', path_png, path_emf])