การเข้ารหัสไฟล์ภาพด้วย base64


161

ฉันต้องการเข้ารหัสภาพเป็นสตริงโดยใช้โมดูล base64 ฉันเจอปัญหาแล้ว ฉันจะระบุรูปภาพที่ต้องการเข้ารหัสได้อย่างไร ฉันลองใช้ไดเรกทอรีไปยังรูปภาพ แต่เพียงนำไปสู่ไดเรกทอรีที่ถูกเข้ารหัส ฉันต้องการเข้ารหัสไฟล์ภาพจริง

แก้ไข

ฉันลองตัวอย่างนี้:

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

แต่ฉันได้รับข้อผิดพลาดต่อไปนี้:

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

ผมทำอะไรผิดหรือเปล่า?

คำตอบ:


299

ฉันไม่แน่ใจว่าฉันเข้าใจคำถามของคุณ ฉันคิดว่าคุณกำลังทำบางสิ่งตามแนวของ:

import base64

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

คุณต้องเปิดไฟล์ก่อนและอ่านเนื้อหา - คุณไม่สามารถผ่านเส้นทางไปยังฟังก์ชั่นการเข้ารหัสได้

แก้ไข: ตกลงนี่คือการอัปเดตหลังจากคุณแก้ไขคำถามเดิมของคุณแล้ว

ก่อนอื่นอย่าลืมใช้สตริงดิบ (นำหน้าสตริงด้วย 'r') เมื่อใช้ตัวคั่นพา ธ บน Windows เพื่อป้องกันการกดปุ่มอักขระโดยไม่ตั้งใจ ประการที่สอง Image.open ของ PIL ยอมรับชื่อไฟล์หรือไฟล์ที่คล้ายกัน (นั่นคือวัตถุจะต้องให้วิธีการอ่านค้นหาและบอก)

ดังที่ได้กล่าวไว้คุณสามารถใช้ cStringIO เพื่อสร้างวัตถุดังกล่าวจากบัฟเฟอร์หน่วยความจำ:

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
ขอบคุณอีกปัญหาหนึ่งเมื่อฉันพิมพ์ภาพถอดรหัสฉันได้รับสตริง 'stringØÿà' อย่างไรก็ตามเมื่อฉันเรียกใช้เพียงอย่างเดียวแทนข้อมูลฉันได้รับข้อผิดพลาด สตริงที่เข้ารหัสมีความยาวกว่ามากสำหรับการเปรียบเทียบ ดังนั้นฉันคิดว่าน่าจะเก็บข้อมูลภาพ สตริงถอดรหัสไม่เพียงอ้างอิงสตริงที่เข้ารหัสหรืออะไร? ดูเหมือนว่าสั้นเกินไปสำหรับการจัดเก็บข้อมูล
สี่เหลี่ยมจตุ

ผลลัพธ์ที่พิมพ์ไม่จำเป็นต้องเท่ากับเนื้อหาจริง - มันขึ้นอยู่กับวิธีและที่คุณพิมพ์
จิมบริสซัม

8
ในกรณีของฉันฉันต้องถอดรหัส: base64.b64encode(fh.read()).decode()เพื่อให้ได้สตริงที่จะใช้ในไฟล์ html
QED

1
base64.b64encode (fh.read ()). decode ()บอบบาง แต่ฉันต้องการสิ่งนี้เช่นกัน @ qed ขอบคุณ ข้อแตกต่างคือผลตอบแทนไบต์และสตริงอื่น ๆ ... และเซิร์ฟเวอร์ SOAP ของฉันจะไม่กลืนโดยไม่ต้องถอดรหัส
zzart

57

ด้วย python 2.x คุณสามารถเข้ารหัสได้โดยใช้. encode:

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

12

คำตอบแรกจะพิมพ์สตริงที่มีคำนำหน้า b ' นั่นหมายความว่าสตริงของคุณจะเป็นเช่นนี้ b'your_string 'เพื่อแก้ปัญหานี้โปรดเพิ่มบรรทัดของรหัสต่อไปนี้

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

2
นี่เป็นคำตอบที่ดี แต่โปรดงดเว้นการโพสต์หากมีวัตถุประสงค์เพื่อโปรโมตเว็บไซต์ของคุณ อย่างไรก็ตามคุณสามารถเพิ่มลิงค์ในโปรไฟล์ของคุณได้
halfer

1
(อนึ่งเพื่อคำตอบที่ไม่สามารถเป็นที่พึ่งที่นี่ดังนั้นจึงเป็นมูลค่าการหลีกเลี่ยงความเห็นเช่น "คำตอบแรก" หนึ่งที่ปรากฏขึ้นครั้งแรกอาจมีการเปลี่ยนแปลงอยู่ตลอดเวลา.. :-))
halfer

ในคำตอบฉบับดั้งเดิมของคุณดูเหมือนว่าคุณลิงก์ไปยังเว็บไซต์ของคุณเองหรือเว็บไซต์ที่คุณเข้าร่วม ถ้าคุณทำเช่นการเชื่อมโยงไปยังเว็บไซต์ดังกล่าวคุณจะต้องเปิดเผยว่ามันเป็นเว็บไซต์ของคุณ หากคุณไม่เปิดเผยการเป็นพันธมิตรถือว่าเป็นสแปม ดู: การส่งเสริมตัวเองของ "ดี" หมายถึงอะไร? และศูนย์ช่วยเหลือในการส่งเสริมตนเอง การเปิดเผยจะต้องชัดเจน แต่ไม่จำเป็นต้องเป็นทางการ เมื่อเป็นเนื้อหาส่วนตัวของคุณเองมันอาจเป็นแค่ "บนไซต์ของฉัน ... ", "ในบล็อกของฉัน ... ", ฯลฯ
Makyen

ขอบคุณสำหรับคำแนะนำ @Makyen ฉันจะเปิดเผยว่าเป็นเว็บไซต์ของฉัน การแก้ไขคำตอบจะเป็นการถูกต้องตามกฎหมายหรือไม่หากเปิดเผยว่าเป็นเว็บไซต์ของฉัน หรือฉันไม่ควรแก้ไข
CodeSpeedy

9

ดังที่ฉันได้กล่าวไปแล้วในคำถามก่อนหน้านี้คุณไม่จำเป็นต้อง base64 เข้ารหัสสตริงมันจะทำให้โปรแกรมช้าลงเท่านั้น เพียงแค่ใช้การรี

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

ตอนนี้ภาพจะถูกเก็บไว้เป็นตัวแปรที่เรียกว่าimage_dataในไฟล์ที่เรียกว่าimage.py เริ่มล่ามสดและนำเข้า image_data

>>> from image import image_data
>>>

ฉันไม่เห็นว่า repr () สามารถใช้งานที่นี่ได้อย่างไร
Ivo van der Wijk

6
@Ivo, Anteater ต้องการเก็บรูปภาพในไฟล์ python ฉันกำลังชี้ให้เห็นว่าการใช้ base64 นั้นไม่ได้ผลเพราะต้องถอดรหัสข้อมูลทุกครั้งที่โหลดโมดูล ใช้ ref แทนหมายถึงสตริงตัวอักษรจะถูกเก็บไว้พร้อมใช้งานได้ทันทีในไฟล์. pyc ที่ไม่มีการประมวลผลเพิ่มเติม
John La Rooy

7

การกู้ยืมจากสิ่งที่Ivo van der Wijkและgnibblerได้พัฒนาไปก่อนหน้านี้เป็นโซลูชั่นแบบไดนามิก

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

จากนั้นคุณสามารถตัดสินใจที่จะรวบรวมไฟล์ภาพออกด้วยCythonเพื่อทำให้มันเย็น ด้วยวิธีนี้คุณสามารถรวมกราฟิกทั้งหมดของคุณไว้ในโมดูลเดียว


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.