Bir görüntü dosyasını base64 ile kodlama


161

Bir görüntüyü base64 modülünü kullanarak bir dizeye kodlamak istiyorum. Yine de bir sorunla karşılaştım. Kodlanmasını istediğim görüntüyü nasıl belirlerim? Görüntüye dizini kullanarak denedim, ama bu sadece kodlanan dizine yol açar. Gerçek görüntü dosyasının kodlanmasını istiyorum.

DÜZENLE

Bu parçacığı denedim:

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))

ama aşağıdaki hatayı alıyorum:

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

Neyi yanlış yapıyorum?

Yanıtlar:


299

Sorunu anladığımdan emin değilim. Sanırım şu şeyler boyunca bir şeyler yapıyorsunuz:

import base64

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

Tabii ki önce dosyayı açıp içeriğini okumalısınız - kodlama işlevinin yolunu geçemezsiniz.

Düzenleme: Tamam, orijinal sorunuzu düzenledikten sonra bir güncelleme.

Her şeyden önce, yanlışlıkla bir kaçış karakterine çarpmasını önlemek için Windows'ta yol sınırlayıcıları kullanırken ham dizeleri ('r' ile önek) kullanmayı unutmayın. İkincisi, PIL'in Image.open dosyası bir dosya adını veya dosya benzeri bir dosyayı kabul eder (yani, nesne okuma, arama ve anlatma yöntemleri sağlamalıdır).

Bununla birlikte, bir bellek arabelleğinden böyle bir nesne oluşturmak için cStringIO'yu kullanabilirsiniz:

import cStringIO
import PIL.Image

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

img = PIL.Image.open(file_like)
img.show()

1
Teşekkürler, kod çözülmüş görüntüyü yazdırdığımda bir sorun daha var 'ÿØÿà' dizesini alıyorum. Ancak, bunu tek başına veri yerine çalıştırdığımda hata alıyorum. Kodlanan dize karşılaştırma için çok daha uzundur. Bu yüzden muhtemelen görüntü verisini depoladığını düşünüyorum. kodu çözülen dize sadece kodlanmış dizeye veya başka bir şeye atıfta bulunuyor mu? Veri depolama için çok kısa görünüyor.
dikdörtgen

Yazdırılan çıktı mutlaka gerçek içeriğe eşit değildir - nasıl ve nereye yazdırdığınıza bağlıdır.
Jim Brissom

8
Benim durumumda, kod çözme gerekiyor: base64.b64encode(fh.read()).decode()html dosyalarında kullanılacak bir dize almak için.
qed

1
base64.b64encode (fh.read ()). decode () ince ama buna da ihtiyacım var @qed, teşekkürler. Fark bir bayt ve diğer dize döndürür ... ve SOAP sunucum sadece kod çözmeden yutmaz!
zzart

57

Python 2.x ile .encode kullanarak önemsiz bir şekilde kodlayabilirsiniz:

with open("path/to/file.png", "rb") as f:
    data = f.read()
    print data.encode("base64")

12

İlk cevap b 'ön ekine sahip bir dize yazdıracaktır. Bu, dizenizin şu şekilde olacağı anlamına gelir b'your_string 'Bu sorunu çözmek için lütfen aşağıdaki kod satırını ekleyin.

encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))

2
Bu iyi bir yanıt gibi görünüyor, ancak amaç web sitenizi tanıtmaksa lütfen göndermekten kaçının. Bununla birlikte, profilinize bağlantılar ekleyebilirsiniz.
halfer

1
(Bu arada, cevap sırasına güvenilemez, bu yüzden "ilk cevap" gibi yorumlardan kaçınmaya değer. İlk görünen cevap zamanla değişebilir. :-))
halfer

Bu cevabın orijinal versiyonunda, kendi sitenize veya bağlı olduğunuz bir siteye bağlandığınız anlaşılıyor. Böyle bir siteye bağlantı verirseniz , sitenizin siteniz olduğunu açıklamanız gerekir . Bağlantıyı açıklamazsanız spam olarak kabul edilir. Bakınız: "İyi" kendini tanıtmanın anlamı nedir? ve kendi kendini tanıma konusunda yardım merkezi . İfşa açık olmalı, ancak resmi olması gerekmez. Kendi kişisel içeriğiniz olduğunda, "sitemde ...", "
blogumda

@Makyen'in önerisi için teşekkür ederim. Sitem olduğunu açıklayacağım. Cevabın sitem olduğunu açıklamak için cevabı şimdi düzenlemek yasal olacak mı? Yoksa düzenlememeliyim.
CodeSpeedy

9

Önceki sorunuzda söylediğim gibi, base64 dizeyi kodlamaya gerek yoktur, sadece programı yavaşlatır. Sadece repr kullanın

>>> 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))
...

Artık görüntü Yeni bir tercüman başlat image_dataadlı bir dosyada çağrılan bir değişken olarak saklanıyor image.pyve image_data dosyasını içe aktarıyor

>>> from image import image_data
>>>

Burada repr () nasıl bir yarar olabilir gerçekten görmüyorum.
Ivo van der Wijk

6
@Ivo, Anteater görüntüleri python dosyalarında saklamak istiyor. Base64 kullanmanın verimsiz olduğunu belirtiyorum çünkü modül her yüklendiğinde verinin kodunun çözülmesi gerekiyor. Bunun yerine repr kullanmak, değişmez dizginin furthur işlemesi olmadan .pyc dosyasında hemen kullanıma hazır olarak depolandığı anlamına gelir
John La Rooy

7

Neyin borç İvo Wijk der van ve gnibbler önceki geliştirdik, bu dinamik çözüm

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')

Daha sonra çıktı görüntü dosyasını Cython ile derlemeye karar verebilirsiniz . Bu yöntemle, tüm grafiklerinizi tek bir modülde toplayabilirsiniz.


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')

1
bu cevap gerçekten en üstte olmalı ... en iyisi - teşekkürler!
Luther
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.