7

I generate an image with Python, and I need to convert this Pil Image into a Base64, without saving this one into any folder...

I have some data, and I get RGB img with the line below:

img = Image.fromarray(data,'RGB')

What is the simple way to convert this PIL into base64 ?(I can't open a file image because I must not save the img) ?

Thank you for your help

With Node JS, I can get the correct base64 with these lines :

pythonShell= require("python-shell");

app.post('/index/gen/',urlencodedParser, function (req,res){ 
  pythonShell.run('minigen.py', function (err, results) {
  if (err) throw err; 
  var img = base64img.base64Sync('./images/miniature.jpg');
  res.send(img); }); 
}) 

But I have to save the file if I use NodeJS...

this is the code to generate the matrix from the image, you don't need to know what is in data ;)

image = Image.open("./carte/"+fichier)              
image = image.resize((400,400),Image.ANTIALIAS)     
w,h = image.size                                    
tab = numpy.array(image)                            
data = numpy.zeros((h, w, 3), dtype=numpy.uint8)
florian
  • 367
  • 2
  • 4
  • 14
  • are you sure you want to convert the PIL? i would have thought it would make more sense to convert you `data` array? – James Kent Jan 12 '18 at 15:36
  • I must convert the data into an RGB image.And then convert this image object to base64 – florian Jan 12 '18 at 15:38
  • Possible duplicate of [Is it possible to create encodeb64 from Image object?](https://stackoverflow.com/questions/16065694/is-it-possible-to-create-encodeb64-from-image-object) – bv. Feb 13 '19 at 14:14

4 Answers4

12

I found the solution. Hope this helps !

img = Image.fromarray(data, 'RGB')                  #Crée une image à partir de la matrice
buffer = BytesIO()
img.save(buffer,format="JPEG")                  #Enregistre l'image dans le buffer
myimage = buffer.getvalue()                     
print "data:image/jpeg;base64,"+base64.b64encode(myimage)
florian
  • 367
  • 2
  • 4
  • 14
11

@florian answer helped me a lot but base64.b64encode(img_byte) returned bytes so I needed to decode it to string before concatenation (using python 3.6):

def img_to_base64_str(self, img):
    buffered = BytesIO()
    img.save(buffered, format="PNG")
    buffered.seek(0)
    img_byte = buffered.getvalue()
    img_str = "data:image/png;base64," + base64.b64encode(img_byte).decode()
Taha Mahjoubi
  • 372
  • 4
  • 10
8

You can use base64 library like this:

import base64

base64.b64encode(img.tobytes())

See tobytes() method of Image object.

Tomáš Linhart
  • 9,832
  • 1
  • 27
  • 39
  • After the conversion into RGB image ? I don't have correct values by doing this – florian Jan 12 '18 at 15:43
  • @florian What do you mean by *correct values*? Base64 just encodes binary data into ASCII characters, which is what you asked for. – Tomáš Linhart Jan 12 '18 at 15:46
  • Our API also works with nodejs and as we try to do the same thing with it, we can display the image in our navigator... Which is impossible with the base64 that we obtain with your method – florian Jan 12 '18 at 15:53
  • 1
    Where do `data` in `img = Image.fromarray(data,'RGB') ` come from and what do they represent? There's a warning regarding compressed formats like JPEG in the documentation to `Image.tobytes()` method that I referenced in the answer. – Tomáš Linhart Jan 12 '18 at 17:18
  • it's the matrix from the image – florian Jan 12 '18 at 17:24
  • 1
    Can you share the part of code that populates that `data` object? – Tomáš Linhart Jan 12 '18 at 17:30
  • If `data = numpy.zeros((h, w, 3), dtype=numpy.uint8)` isn't it just all zero? Probably something you didn't want. – Tomáš Linhart Jan 12 '18 at 18:07
  • No, don't worry, the script make many colors for an altimetric map ;) – florian Jan 12 '18 at 20:09
2

Or you can use something like this:

import glob
import random
import base64

from PIL import Image
from io import BytesIO
import io


def get_thumbnail(path):
    path = "\\\\?\\"+path # This "\\\\?\\" is used to prevent problems with long Windows paths
    i = Image.open(path)    
    return i

def image_base64(im):
    if isinstance(im, str):
        im = get_thumbnail(im)
    with BytesIO() as buffer:
        im.save(buffer, 'jpeg')
        return base64.b64encode(buffer.getvalue()).decode()

def image_formatter(im):
    return f'<img src="data:image/jpeg;base64,{image_base64(im)}">'

Just pass path of image in get_thumbnail function and image_formatter to display it in HTML.

Hrvoje
  • 13,566
  • 7
  • 90
  • 104