Forum Archive

Uploading from camera library via xmlrpclib

Sigafoos

I couldn't find anything else in the forums, but I'm trying to upload an image to a Wordpress site via xmlrpclib. I was able to do it with an image hosted online using this code:

def new_image(url, post_id = None):
    import urllib2
    from re import findall

    raw = urllib2.urlopen(url)
    image = raw.read()

    content = {}
    content['bits'] = xmlrpclib.Binary(image)

    content['name'] = findall('[^\/]+?$',url)[0]
    content['type'] = 'image/jpeg'
    if post_id is not None:
        content['post_id'] = post_id

    img = server.wp.uploadFile(1,username,password,content)
    return img

(server, username and password are defined earlier)

I'm trying to do the same thing with an image chosen from my camera roll (I go through my company's Instagram feed and upload it for a weekly blog post, but sometimes I have a 4:3 version I want to use instead). To get content['bits'] I'm using:

import photos

image = photos.pick_image(False, True, False)
image[0].verify()

content = {}
content['bits'] = xmlrpclib.Binary(image[0].tostring())

This... works, in that an object is returned, but the image doesn't actually upload. See this example.

File and I/O stuff are what I hate most about coding, and I don't really understand all the components, so maybe (hopefully) there's something easy I'm missing.

JonB

See Image.tostring()

Image.tostring(encoder, parameters)

Returns a string containing pixel data, using the given data encoding.

Note: The tostring method only fetches the raw pixel data. To save the image to a string in a standard file format, pass a StringIO object (or equivalent) to the save method.

tostring is not returning the binary of an encoded image file, but more like the binary underlying the PIL image format. Use save instead with a StringIO object, then use getValue to get the binary.

See https://omz-forums.appspot.com/pythonista/post/5520750224080896 for the basic approach, except you won't then convert to a ui.Image.

Sigafoos

Thank you! But now I'm having trouble with .save():

with io.BytesIO() as bIO:
    image[0].save(bIO,'JPG')
    content['bits'] = bIO.getvalue()

The second line gives KeyError: 'JPG'. So I thought it might be interpreting that as an option and not format I added {'quality': 80} and got TypeError: save() takes at most 3 arguments (4 given)

So... It thinks there's an extra argument? To make sure image[0] was correct I did .show() and it worked...

JonB

Use 'jpeg ', not 'jpg'.

Actually, if you don't need to manipulate it at all, use the raw_data=True argument to pick_image , which returns the raw binary without having to use save, etc.

Sigafoos

Wonderful, thank you!

Using JPEG still didn't work, so I went the raw_data route, and it works perfectly. For posterity:

content = {}
image = photos.pick_image(False, True, True ,True )
content['bits'] = xmlrpclib.Binary(image[0])