unotools insert image into document (libreoffice) - python

I'm trying to insert an image into a libreoffice document that is handled/controlled by unotools.
Therefore I start LibreOffice with this command:
soffice --accept='socket,host=localhost,port=8100;urp;StarOffice.Service'
Inside my python code I can connect to LibreOffice:
from unotools import Socket, connect
from unotools.component.writer import Writer
context = connect(Socket('localhost', 8100))
writer = Writer(context)
(This code is taken from this documentation: https://pypi.org/project/unotools/)
By using writer.set_string_to_end() I can add some text to the document. But I also want to insert an image into the document. So far I couldn't find any resource where this was done. The image is inside of my clipboard, so ideally I want to insert the image directly from there. Alternatively I can save the image temporarily and insert the saved file.
Is there any known way how to insert images by using unotools? Any alternative solution would also be great.

I've found a way to insert images by using uno instead of unotools:
import uno
from com.sun.star.awt import Size
from pythonscript import ScriptContext
def connect_to_office():
if not 'XSCRIPTCONTEXT' in globals():
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext(
'com.sun.star.bridge.UnoUrlResolver', localContext )
client = resolver.resolve("uno:socket,host=localhost,port=8100;urp;StarOffice.ComponentContext" )
global XSCRIPTCONTEXT
XSCRIPTCONTEXT = ScriptContext(client, None, None)
def insert_image(doc):
size = Size()
path = uno.systemPathToFileUrl('/somepath/image.png')
draw_page = self.doc.DrawPage
image = doc.createInstance( 'com.sun.star.drawing.GraphicObjectShape')
image.GraphicURL = path
draw_page.add(image)
size.Width = 7500
size.Height = 5000
image.setSize(size)
image.setPropertyValue('AnchorType', 'AT_FRAME')
connect_to_office()
doc = XSCRIPTCONTEXT.getDocument()
insert_image(doc)
sources:
https://ask.libreoffice.org/en/question/38844/how-do-i-run-python-macro-from-the-command-line/
https://forum.openoffice.org/en/forum/viewtopic.php?f=45&t=80302
I still don't know how to insert an image from my clipboard, I worked around that problem by saving the image first. If someone knows a way to insert the image directly from the clipboard that would still be helpful.

Related

How to delete an image using default_storage.delete(file_name) in Django View?

So I have been creating a Fingerprint Matching system using Django Rest Framework. Whenever I send a fingerprint from frontend to backend to match with the stored fingerprints. The fingerprint is getting stored there which is not what I want. I want to delete it once it's use is over.
Here is the Error Image: https://i.stack.imgur.com/MCXcv.png
def post(self, request, format = None):
serializer = serializers.MatchSerializer(data = request.data)
if serializer.is_valid():
#Fetching the stored fingerprints in a different serializer.
queryset = models.Profile.objects.all()
serializer2 = serializers.ProfileSerializer(queryset, many=True)
data = serializer2.data
#Initialized a result list which will be appended with the name of the user whose
#fingerprint is matched.
result = []
file = request.FILES['fingerprint']
file_name = default_storage.save(file.name, file)
file = default_storage.open(file_name)
file_url = default_storage.url(file_name)
fImage = cv2.imread(str(file))
for i in range(len(data)):
print(data[i].get('fingerprint'))
DbImage = cv2.imread('C:/Users/ShalomAlexander/Documents/4th Year
Project/Django/FingerprintMatch/' + data[i].get('fingerprint'))
if(isMatch(fImage, DbImage)):
result.append(data[i].get('name'))
#This is not working as expected because its raising an error ie. " Process is still
#in use"
default_storage.delete(file_name)
return Response(result)
If you have any better approach to match fingerprints or images that will also be appreciated. Thanks in advance. The current code works fine and matches the fingerprint as expected but its storing the incoming fingerprint image and I don't want that.
For me this problem was solved using file_path instead of file_name:
file_name = default_storage.save(file.name, file)
file_path = os.path.join(settings.MEDIA_ROOT, file_name)
. . .
default_storage.delete(file_path)
file = default_storage.open(file_name)
...
default_storage.delete(file_name)
That is why that file is open when you try to delete it.
This has nothing to do with OpenCV. The point of a minimal reproducible example is to make you figure out where the issue is.
It looks like more an opencv issue than django-rest-framework's one.
Please refer to this issue:
https://github.com/opencv/opencv/issues/12342
Looks like your solution might be just to upgrade your opencv package version.

Retrieve and show image from MongoDB using PyMongo

I am using PyMongo to retrieve collection data as dictionary and then trying to convert the image key's respective value from the dict to proper base64 encoded string to show the image, but it doesn't just work. When I use mongoengine, it works fine as the string returned from the latter is b64 encoded already, unlike PyMongo.
Following is my sample working Mongoengine code to retrieve a respective image and show as Pillow image:
from mongoengine import connect, Document, fields
import mongoengine
import io
import PIL.Image as Image
print(mongoengine.__version__)
# To save image
connect(db='video_analytics', host='127.0.0.1', port=27017)
class User(Document):
meta = {"collection": "users"}
username = fields.StringField(required=True)
profile_image = fields.ImageField(thumbnail_size=(150, 150, False))
user = User.objects(username='Doggy').first()
# print(user)
img_data = user.profile_image.read()
# Test
print(img_data)
# Ends
bytes = bytearray(img_data)
image = Image.open(io.BytesIO(bytes))
print(image)
# image.show()
And following is my PyMongo code which gives no error but doesn't show the image:
client = MongoClient("mongodb://127.0.0.1:27017/")
# select database
db = client['frame_read']
# select the collection within the database
test = db["random"]
# print("collections count -->" + str(test.count()))
cursor = test.find()
for rec in cursor:
# print(rec['profile_image'])
f = rec['profile_image']
img = Image.open(f)
print(img.size)
img.show()
I tried many ways, but it is just not working. Here I read by default MongoDB stores in BSON bytes format. Is there a way how to retrieve data properly?
I followed this too, but to no avail.
Note: I'm intentionally not using GridFS because my image size is much lesser than 16 MB. If you say GridFS is still better performant for retrieval, then I shall plan using the same.

cURL method in Python for JSON feed [duplicate]

This question already has answers here:
How to download a file over HTTP?
(30 answers)
Closed 7 years ago.
While building a flask website, I'm using an external JSON feed to feed the local mongoDB with content. This feed is parsed and fed while repurposing keys from the JSON to keys in Mongo.
One of the available keys from the feed is called "img_url" and contains, guess what, an url to an image.
Is there a way, in Python, to mimic a php style cURL? I'd like to grab that key, download the image, and store it somewhere locally while keeping other associated keys, and have that as an entry to my db.
Here is my script up to now:
import json
import sys
import urllib2
from datetime import datetime
import pymongo
import pytz
from utils import slugify
# from utils import logger
client = pymongo.MongoClient()
db = client.artlogic
def fetch_artworks():
# logger.debug("downloading artwork data from Artlogic")
AL_artworks = []
AL_artists = []
url = "http://feeds.artlogic.net/artworks/artlogiconline/json/"
while True:
f = urllib2.urlopen(url)
data = json.load(f)
AL_artworks += data['rows']
# logger.debug("retrieved page %s of %s of artwork data" % (data['feed_data']['page'], data['feed_data']['no_of_pages']))
# Stop we are at the last page
if data['feed_data']['page'] == data['feed_data']['no_of_pages']:
break
url = data['feed_data']['next_page_link']
# Now we have a list called ‘artworks’ in which all the descriptions are stored
# We are going to put them into the mongoDB database,
# Making sure that if the artwork is already encoded (an object with the same id
# already is in the database) we update the existing description instead of
# inserting a new one (‘upsert’).
# logger.debug("updating local mongodb database with %s entries" % len(artworks))
for artwork in AL_artworks:
# Mongo does not like keys that have a dot in their name,
# this property does not seem to be used anyway so let us
# delete it:
if 'artworks.description2' in artwork:
del artwork['artworks.description2']
# upsert int the database:
db.AL_artworks.update({"id": artwork['id']}, artwork, upsert=True)
# artwork['artist_id'] is not functioning properly
db.AL_artists.update({"artist": artwork['artist']},
{"artist_sort": artwork['artist_sort'],
"artist": artwork['artist'],
"slug": slugify(artwork['artist'])},
upsert=True)
# db.meta.update({"subject": "artworks"}, {"updated": datetime.now(pytz.utc), "subject": "artworks"}, upsert=True)
return AL_artworks
if __name__ == "__main__":
fetch_artworks()
First, you might like the requests library.
Otherwise, if you want to stick to the stdlib, it will be something in the lines of:
def fetchfile(url, dst):
fi = urllib2.urlopen(url)
fo = open(dst, 'wb')
while True:
chunk = fi.read(4096)
if not chunk: break
fo.write(chunk)
fetchfile(
data['feed_data']['next_page_link'],
os.path.join('/var/www/static', uuid.uuid1().get_hex()
)
With the correct exceptions catching (i can develop if you want, but i'm sure the documentation will be clear enough).
You could put the fetchfile() into a pool of async jobs to fetch many files at once.
https://docs.python.org/2/library/json.html
https://docs.python.org/2/library/urllib2.html
https://docs.python.org/2/library/tempfile.html
https://docs.python.org/2/library/multiprocessing.html

uploading multiple models to sketchfab

The follwowing is a code written in blender python
import bpy
import os
import subprocess
import time
bpy.data.materials["Material"].use_face_texture = True
customer_id = "john33"
image1 = "orangeskin.jpg" # define image 1 from folder
imagepath1 = "C:\\Users\\mrryan\\Desktop\\models\\materialsjpeg\\"
image2 = "elec.jpg"
imagepath2 = "C:\\Users\\mrryan\\Desktop\\models\\materialsjpeg\\"
#Step 1 go to Edit Mode
bpy.ops.object.editmode_toggle()
#step 2 insert image in the Image Editor
bpy.context.area.type = 'IMAGE_EDITOR'
bpy.ops.uv.smart_project()
bpy.ops.image.open(filepath = image1, directory= imagepath1 ,
files=[{"name":image1, "name":image1}])
#Step 3 back to Object Mode TRY AND CHANGE TITLE TO `CUSTOMER_ID AND FILE`
bpy.ops.object.editmode_toggle()
bpy.data.window_managers["WinMan"].sketchfab.title = "orangetube"
#Step 4 save new.blend
filepath = os.path.join(r"C:\Users\mrryan\Desktop", customer_id + "orangytube.blend")
bpy.ops.wm.save_as_mainfile(filepath = filepath)
toggleedit = bpy.ops.object.editmode_toggle()
#here is the problem!!!!
subprocess.call(["bpy.ops.export.sketchfab()"], shell = True)
#new texture
#Step 1 go to Edit Mode
#step 2 insert image in the Image Editor
bpy.context.area.type = 'IMAGE_EDITOR'
bpy.ops.image.open(filepath= image2, directory= imagepath2,
files= [{"name":image2,"name":image2}])
bpy.ops.uv.smart_project()
#Step 3 back to Object Mode
bpy.ops.object.editmode_toggle()
bpy.data.window_managers["WinMan"].sketchfab.title = "elec-tube"
#Step 4 save new.blend
filepath = os.path.join(r"C:\Users\mrryan\Desktop", customer_id + "elec-tube.blend")
bpy.ops.wm.save_as_mainfile(filepath = filepath)
bpy.ops.export.sketchfab()
The idea is, eventually to programmatically change the active object( which is combined but not joined with another object) to have different materials and change the shape, etc. Each individual model combination would be uploaded to sketchfab separately and saved as a blender file.
At this stage my problem is that, while uploading, the script does not wait until the first upload is finished.This generates an error that says to please wait for the current upload to finish. and as a result only one model is uploaded.
subprocess.Popen
has been tried but i could not get it to work.
Perhaps the return values were wrong?
How can you get the script to upload the first model, wait until finished, then continue to make the adjustments and upload the second?
(I work at Sketchfab, but I don't have much experience in Blender scripting).
The issue is that the Sketchfab Blender Exporter uses a thread for the upload, meaning the subprocess will return, with a thread still running in the background.
I would experiment in launching bpy.ops.export.sketchfab() using a new Thread and join(), instead of just subprocess.
The following resources might help:
python multithreading wait till all threads finished
https://docs.python.org/2/library/multiprocessing.html
http://www.blender.org/documentation/blender_python_api_2_62_2/info_gotcha.html#strange-errors-using-threading-module
Let us know how it goes!

insert image in text widget without using imageTK

Unfortunately I'm developing under a osx machine where I've been unable to install imageTK...
I need to insert an image taken from a dictionary of images, saved thus:
i = open(filename, 'rb')
i.seek(0)
w = i.read()
i.close()
allicons[d]=w
so at insert time I don't have a filename, just the dict.
with imageTk, this works:
c = cStringIO.StringIO()
c.write(allicons[key])
c.seek(0)
im = Image.open(c)
iconimage=ImageTk.PhotoImage(im)
config.text.image_create(INSERT, image=iconimage)
but I don't know how to do it without imageTk.
Just with "import Image", I tried:
im = Image.open(c)
iconimage = PhotoImage(im)
and iconimage is recognized (TkInter.PhotoImage object ...),
but inserting it I get a "TypeError: str returned non-string (type instance) ... in image_create *self._options(cnf, kw))"
... any help really appreciated, thanks!
alessandro
PhotoImage has a 'data' option. You can supply it with gif data that's been encoded using base64. something like:
dat = base64.encodestring(allicons[key])
pic = PhotoImage(data=dat)
...

Categories

Resources