Pengkodean file gambar dengan base64

161

Saya ingin menyandikan gambar menjadi string menggunakan modul base64. Saya pernah mengalami masalah. Bagaimana cara menentukan gambar yang ingin saya disandikan? Saya mencoba menggunakan direktori ke gambar, tetapi itu hanya mengarah ke direktori yang dikodekan. Saya ingin file gambar aktual dikodekan.

EDIT

Saya mencoba cuplikan ini:

with open("C:\Python26\seriph1.BMP", "rb") as f:
    data12 = f.read()
    UU = data12.encode("base64")
    UUU = base64.b64decode(UU)

    print UUU

    self.image = ImageTk.PhotoImage(Image.open(UUU))

tapi saya mendapatkan kesalahan berikut:

Traceback (most recent call last):
  File "<string>", line 245, in run_nodebug
  File "C:\Python26\GUI1.2.9.py", line 473, in <module>
    app = simpleapp_tk(None)
  File "C:\Python26\GUI1.2.9.py", line 14, in __init__
    self.initialize()
  File "C:\Python26\GUI1.2.9.py", line 431, in initialize
    self.image = ImageTk.PhotoImage(Image.open(UUU))
  File "C:\Python26\lib\site-packages\PIL\Image.py", line 1952, in open
    fp = __builtin__.open(fp, "rb")
TypeError: file() argument 1 must be encoded string without NULL bytes, not str

Apa yang saya lakukan salah?

persegi panjang
sumber

Jawaban:

299

Saya tidak yakin saya mengerti pertanyaan Anda. Saya berasumsi Anda sedang melakukan sesuatu seperti:

import base64

with open("yourfile.ext", "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())

Anda harus membuka file terlebih dahulu, dan membaca isinya - Anda tidak bisa hanya meneruskan jalur ke fungsi penyandian.

Sunting: Oke, ini pembaruan setelah Anda mengedit pertanyaan awal Anda.

Pertama-tama, ingatlah untuk menggunakan string mentah (awali string dengan 'r') saat menggunakan pembatas jalur pada Windows, untuk mencegah agar tidak sengaja mengenai karakter escape. Kedua, PIL's Image.open menerima nama file, atau seperti file (yaitu, objek harus menyediakan metode membaca, mencari, dan memberi tahu).

Yang sedang berkata, Anda dapat menggunakan cStringIO untuk membuat objek seperti itu dari buffer memori:

import cStringIO
import PIL.Image

# assume data contains your decoded image
file_like = cStringIO.StringIO(data)

img = PIL.Image.open(file_like)
img.show()
Jim Brissom
sumber
1
Terima kasih, satu masalah lagi ketika saya mencetak gambar yang di-decode saya mendapatkan string 'ÿØÿà'. Namun, ketika saya menjalankan ini sendiri sebagai pengganti data saya mendapatkan kesalahan. String yang disandikan jauh lebih lama untuk perbandingan. Jadi saya pikir itu kemungkinan menyimpan data gambar. apakah string yang didekodekan hanya merujuk string yang disandikan atau sesuatu? Tampaknya terlalu pendek untuk penyimpanan data.
rectangletangle
Hasil cetak tidak harus sama dengan konten yang sebenarnya - itu tergantung pada bagaimana dan di mana Anda mencetaknya.
Jim Brissom
8
Dalam kasus saya, saya perlu mendekode: base64.b64encode(fh.read()).decode()untuk mendapatkan string yang akan digunakan dalam file html.
qed
1
base64.b64encode (fh.read ()). decode () halus tetapi saya membutuhkan ini juga @qed, terima kasih. Perbedaan adalah satu mengembalikan byte dan string lainnya ... dan server SOAP saya tidak akan menelannya tanpa decoding!
zzart
57

Dengan python 2.x, Anda dapat menyandikan dengan sepele menggunakan .encode:

with open("path/to/file.png", "rb") as f:
    data = f.read()
    print data.encode("base64")
Ivo van der Wijk
sumber
12

Jawaban pertama akan mencetak string dengan awalan b '. Itu artinya string Anda akan seperti ini b'your_string 'Untuk mengatasi masalah ini, tambahkan baris kode berikut.

encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))
CodeSpeedy
sumber
2
Ini sepertinya jawaban yang bagus, tapi tolong jangan memposting jika tujuannya adalah untuk mempromosikan situs web Anda. Anda dipersilakan untuk menambahkan tautan ke profil Anda.
halfer
1
(Kebetulan, urutan jawaban tidak dapat diandalkan di sini, jadi sebaiknya hindari komentar seperti "jawaban pertama". Jawaban yang muncul pertama mungkin berubah seiring waktu. :-))
halfer
Dalam versi asli jawaban ini, sepertinya Anda tertaut ke situs Anda sendiri atau situs yang berafiliasi dengan Anda. Jika Anda menautkan ke situs tersebut, Anda harus mengungkapkan bahwa itu adalah situs Anda . Jika Anda tidak mengungkapkan afiliasi, itu dianggap sebagai spam. Lihat: Apa yang menandakan promosi diri "Bagus"? dan pusat bantuan tentang promosi diri . Pengungkapan harus eksplisit, tetapi tidak perlu formal. Ketika itu adalah konten pribadi Anda , itu bisa saja seperti "di situs saya ...", "di blog saya ...", dll.
Makyen
Terima kasih atas saran @Makyen saya akan mengungkapkan bahwa ini adalah situs saya. Apakah sah untuk mengedit jawaban sekarang untuk mengungkapkan bahwa itu adalah situs saya? Atau saya tidak boleh mengeditnya.
CodeSpeedy
9

Seperti yang saya katakan di pertanyaan Anda sebelumnya, base64 tidak perlu menyandikan string, itu hanya akan membuat program lebih lambat. Cukup gunakan repr

>>> with open("images/image.gif", "rb") as fin:
...  image_data=fin.read()
...
>>> with open("image.py","wb") as fout:
...  fout.write("image_data="+repr(image_data))
...

Sekarang gambar disimpan sebagai variabel yang disebut image_datadalam file yang disebut image.py Mulai penerjemah baru dan impor image_data

>>> from image import image_data
>>>
John La Rooy
sumber
Saya tidak benar-benar melihat bagaimana repr () dapat digunakan di sini.
Ivo van der Wijk
6
@Ivo, Anteater ingin dapat menyimpan gambar dalam file python. Saya menunjukkan bahwa menggunakan base64 kontraproduktif karena data perlu diterjemahkan setiap kali modul dimuat. Menggunakan repr sebagai gantinya berarti string literal disimpan siap untuk segera digunakan dalam file .pyc tanpa pemrosesan lebih lanjut
John La Rooy
7

Meminjam dari apa yang telah dikembangkan Ivo van der Wijk dan gnibbler sebelumnya, ini adalah solusi yang dinamis

import cStringIO
import PIL.Image

image_data = None

def imagetopy(image, output_file):
    with open(image, 'rb') as fin:
        image_data = fin.read()

    with open(output_file, 'w') as fout:
        fout.write('image_data = '+ repr(image_data))

def pytoimage(pyfile):
    pymodule = __import__(pyfile)
    img = PIL.Image.open(cStringIO.StringIO(pymodule.image_data))
    img.show()

if __name__ == '__main__':
    imagetopy('spot.png', 'wishes.py')
    pytoimage('wishes')

Anda kemudian dapat memutuskan untuk mengkompilasi file gambar output dengan Cython untuk membuatnya keren. Dengan metode ini, Anda dapat menggabungkan semua gambar Anda menjadi satu modul.

iChux
sumber
7
import base64
from PIL import Image
from io import BytesIO

with open("image.jpg", "rb") as image_file:
    data = base64.b64encode(image_file.read())

im = Image.open(BytesIO(base64.b64decode(data)))
im.save('image1.png', 'PNG')
Solusi Perangkat Lunak DooDle
sumber
1
jawaban ini benar-benar harus di atas ... terbaik - terima kasih!
Luther