I want to show a jpg image in tkinter.Label using a base64 string that is stored inside a JSON file, but I get the following error:
_tkinter.TclError: couldn't recognize image data
here's my block of code:
import json
import base64
import tkinter as tk
image_data = {}
def image_to_json():
with open("path/to/image.jpg","rb") as image:
data = base64.b64encode(image.read())
image_data["data"]=str(data)
with open("jsonfile.json", "w") as file:
json.dump(image_data, file)
def json_to_image():
with open("jsonfile.json", "rb") as file:
contents = json.load(file)
img_data = contents["data"]
return img_data
if __name__=="__main__":
root = tk.Tk()
image_to_json()
converted_image = tk.PhotoImage(data=json_to_image())
label = tk.Label(root, image = converted_image).pack()
root.mainloop
I've also tried this using a png file and got the same error
You probably have to decode the string properly:
EDITED Try this:
image_data = {}
with open("path/to/image.png", "rb") as image:
data = base64.encodebytes(image.read())#
data = data.decode("utf-8")
image_data["data"] = data
with open("jsonfile.json", "w") as file:
json.dump(image_data, file)
with open("jsonfile.json", "rb") as file:
contents = json.load(file)
image_data = contents["data"]
Then it works:
root = tk.Tk()
converted_image = tk.PhotoImage(data=image_data)
label = tk.Label(root, image = converted_image).pack()
root.mainloop()
Related
I am converting the hexadecimal files to images. The input files are converted to byte string using binascii library. The problem arises when the byte string is written to form an image. The output of all the hexadecimal files is same. I will be grateful if someone provides me a solution.
Here is my code:
import binascii
import cv2
import os
from tkinter import *
from tkinter import filedialog
#Hide the root window that comes by default
root=Tk()
root.withdraw()
#Browse and select txt files
dir=[]
dir=filedialog.askopenfilenames(
initialdir="C:\Binaries\Hexadecimal_Text_Files",
title="Open Text file",
filetypes=(("Text Files", "*.txt"),)
)
#Reading data in txt files and decoding hexadecimal characters
for x in dir:
tf=open(x)#Open file
data=tf.read()#Read data in file
data=data.replace(' ','')#Remove whitespaces
data=data.replace('\n','')#Remove breaks in lines
data=binascii.a2b_hex(data)
tf.close()
#Extract txt filename without extension
pathname, extension = os.path.splitext(f"{x}")#Split path into filename and extenion
filename = pathname.split('/')#Get filename without txt extension
filepath=f"C:\Binaries\Images\{filename[-1]}.png"#Defining name of image file same as txt file
#Write data into image
with open(filepath, 'wb') as image_file:
img=image_file.write(data)
#Resizing Image
img=cv2.resize(img,(500,500))
cv2.imwrite(filepath,img)
Output:
I made my own version because I could not get yours to work, but if you want to make yours work, at least one problem with I found is with this line:
img=cv2.resize(img,(500,500))
by printing all the variables after the supposed "conversion", I found that your variable img in the previous line is not an image but the result of image_file.write(data) which returns the number of bytes written to the file and not the image itself, which is probably why it always prints the same image.
Here is my version
root=Tk()
root.withdraw()
file_path = filedialog.askopenfilename(
initialdir = "C:\Binaries\Images",
title = "Select Hexadecimal Text File",
filetypes = (("Text Files", "*.txt"),)
)
with open(file_path, "r") as hex_file:
hex_data = hex_file.read().replace("\n", "")
#replaces white spaces and new lines from file
binary_data = binascii.a2b_hex(hex_data)
#converts the hexadecimal data to binary
pathname, extension = os.path.splitext(file_path)
image_path = pathname + ".png"
#image path and format
with open(image_path, "wb") as image_file:
image_file.write(binary_data)
#writing the binary data to image file
img = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
#if txt file is empty
if img is None:
print("Error: Image not loaded!")
else:
cv2.imshow("image", img)
#waits for key input and closes when pressing any key
cv2.waitKey(0)
cv2.destroyAllWindows()
I have converted the hexadecimal files into images by using numpy array and Pillow. Now I am getting different images.
import numpy as np
import binascii
import os
from PIL import Image as im
from tkinter import *
from tkinter import filedialog
# Hide the root window that comes by default
root = Tk()
root.withdraw()
# Browse and select txt files
dir = []
dir = filedialog.askopenfilenames(
initialdir="C:\Binaries\Folder_3",
title="Open Text file",
filetypes=(("Text Files", "*.txt"),)
)
# Reading data in txt files and decoding hexadecimal characters
for temp in dir:
tf = open(temp) # Open file
data = tf.read() # Read data in file
data= data.replace('\'','') #Remove label
data = data.replace(' ', '') # Remove whitespaces
data = data.replace('\n', '') # Remove breaks in lines
data = binascii.a2b_hex(data)
tf.close()
#Converting bytes array to numpy array
a = np.frombuffer(data, dtype='uint8')
#print(a) //Display array
#Finding optimal factor pair for size of image
x = len(a)
val1=0
val2=0
for i in range(1, int(pow(x, 1 / 2))+1):
if x % i == 0:
val1=i
val2=int(x / i)
#Converting 1-D to 2-D numpy array
a = np.reshape(a, (val1, val2))
#print(a) #Display 2-D array
#Writing array to image
data = im.fromarray(a)
# Split path into filename and extenion
pathname, extension = os.path.splitext(f"{temp}")
filename = pathname.split('/') # Get filename without txt extension
# Defining name of image file same as txt file
filepath = f"C:\Binaries\Images_3\{filename[-1]}.png"
#Resize image
data=data.resize((500,500))
#Saving image into path
data.save(filepath)
I need that when the button is clicked, the file_name variable is saved to a file. Please tell me how to fix my code:
window = tk.Tk()
window.title("Open")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def openu():
global file_name
if file_name == "":
file_name = tfd.askopenfilename()
with open("Filen.json", "w") as file1:
json.dump(file_name, file1, indent=2, ensure_ascii=False)
os.startfile(file_name)
else:
with open("Filen.json", "r") as file1:
json.load(file1)
os.startfile(file_name)
if btn1["text"] == "":
btn1["text"] = file_name
btn1 = tk.Button(window, text="", command=openu)
btn1.place(x = 20, y = 25)
window.mainloop()
UPD:
When you click on the button, the program opens a dialog box that opens the file. A File.json is created. Everything is displayed, but one thing does not work. I need that when restarting the program, the buttons are not empty. I changed the code, putting the full one.
Here is the code. When the user opens the window, it loads the file path from the json file and automatically sets the button's text. When the user presses the button, it asks for a new file path name. More detailed explanations can be found in the comments in the code.
import tkinter as tk
import tkinter.filedialog as tfd
import json
import os
window = tk.Tk()
window.title("Open")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def load_json():
global file_name
# Load the json file if it exists
if os.path.exists("Filen.json"):
with open("Filen.json") as file1:
contents = json.load(file1)
# If the json has a path in it, load the path to file_name
# Otherwise, set file_name to an empty string ""
if len(contents) > 0:
if contents[0] != "":
file_name = contents[0]
else:
file_name = ""
else:
file_name = ""
# Create the json file if it does not exist
else:
with open("Filen.json", "w") as file1:
json.dump([file_name], file1, indent=2, ensure_ascii=False)
def openu():
global file_name
# Load the json file
load_json()
# If file_name is still "", ask the user to input a file path
path = tfd.askopenfilename()
# If the user gave a path (did not hit Cancel), save path to file_name
# and set the button's label
if path != ():
file_name = path
btn1.config(text=file_name)
# Save file_name to the json file
with open("Filen.json", "w") as file1:
json.dump([file_name], file1, indent=2, ensure_ascii=False)
# Load the json file, and put the file name into the button's text
load_json()
btn1 = tk.Button(window, text=file_name, command=openu)
btn1.place(x = 20, y = 25)
window.mainloop()
#Code Entered
from PIL import Image
import pytesseract as pt
import os
def main():
path ="C:\\Users\\folder1\\folder2"
tempPath ="C:\\Users\\folder1\\newfolder"
for imageName in os.listdir(path):
inputPath = os.path.join(path, imageName)
img = Image.open(inputPath)
text = pt.image_to_string(img, lang ="eng")
fullTempPath = os.path.join(tempPath, 'time_'+imageName+".txt")
print(text)
file1 = open(fullTempPath, "w")
file1.write(text)
file1.apend(text)
if __name__ == '__main__':
main()
`
#Error occured
#AttributeError '_io.TextIOWrapper' object has no attribute 'apend'
#Please help in savin the data in a single file
Does it work if you change:
file1.apend(text)
to
file1.append(text)
?
Also, what is file1.append doing here? If you want to write some data to a file, you're probably best off with:
with open(fullTempPath, "w+") as f:
f.write(text)
This will close the file after you're done writing.
I am trying to OCR an entire directory of pdf files using pytesseract and imagemagick but the issue is that imagemagick is consuming all my Temp folder space and finally I'm getting a cache error i.e "CacheError: unable to extend cache 'C:/Users/Azu/AppData/Local/Temp/magick-18244WfgPyAToCsau11': No space left on device # error/cache.c/OpenPixelCache/3883" I have also written a code to delete the temp folder content once OCR'd but still facing the same issue.
Here's the code till now:
import io
import os
import glob
from PIL import Image
import pytesseract
from wand.image import Image as wi
files = glob.glob(r"D:\files\**")
tempdir = r"C:\Users\Azu\AppData\Local\Temp"
filesall = os.listdir(tempdir)
for file in files:
name = os.path.basename(file).split('.')[0]
#print(file)
pdf = wi(filename = file, resolution = 300)
pdfImg = pdf.convert('jpeg')
imgBlobs = []
for img in pdfImg.sequence:
page = wi(image = img)
imgBlobs.append(page.make_blob('jpeg'))
extracted_texts = []
for imgBlob in imgBlobs:
im = Image.open(io.BytesIO(imgBlob))
text = pytesseract.image_to_string(im, lang = 'eng')
extracted_texts.append(text)
with open("D:\\extracted_text\\"+ name + ".txt", 'w') as f:
f.write(str(extracted_texts))
for ifile in filesall:
if "magick" in ifile:
os.remove(os.path.join(tempdir,ifile))
I came up with this, but how would I shorten this down subtantially for the conventional python shell.
import zlib, sys, time, base64, pymsgbox, ttk
from tkFileDialog import askopenfilename
import Tkinter as tk
def getPath():
path = askopenfilename(filetypes=[("Text Files", (".txt")), ("Text", '.txt'), ('All', '*')], )
return path
def compress():
text = open(getPath(), 'r').read()
realSize = 'Raw size :' + str(sys.getsizeof(text))
print(realSize)
comperesed = base64.b64encode(zlib.compress(text, 9))
compressedSize = 'Raw size :' + str(sys.getsizeof(comperesed))
print(compressedSize)
compressedFile = pymsgbox.prompt('Compressd File Name:') + '.txt'
encoded = open(compressedFile, 'a')
encoded.write(comperesed)
encoded.close()
def decompress():
readFile = open(getPath(), 'r').read()
decompressed = zlib.decompress(base64.b64decode(readFile))
decompressedFile = pymsgbox.prompt('Decompressd File Name:') + '.txt'
decoded = open(decompressedFile, 'a')
decoded.write(decompressed)
decoded.close()
def gui():
# Make Message
pymsgbox.alert('Welcome', 'Compressing and Decompressing')
win = tk.Tk()
win.title("Compressing and Decompressing")
aLabel = ttk.Label(win, text="Compress")
aLabel.grid(column=0, row=0)
aLabel = ttk.Label(win, text="Decompress")
aLabel.grid(column=0, row=1)
action = ttk.Button(win, text="Convert", command=compress)
action.grid(column=1, row=0)
action = ttk.Button(win, text="Convert", command=decompress)
action.grid(column=1, row=1)
win.mainloop()
gui()
If I undestand the question correctly you want to just run the compress and decompress functions from a python shell.
import zlib, sys, base64
def compress(decompressedFile, compressedFile):
text = open(decompressedFile, 'r').read()
realSize = 'Raw size :' + str(sys.getsizeof(text))
print(realSize)
comperesed = base64.b64encode(zlib.compress(text, 9))
compressedSize = 'Raw size :' + str(sys.getsizeof(comperesed))
print(compressedSize)
encoded = open(compressedFile, 'a')
encoded.write(comperesed)
encoded.close()
def decompress(compressedFile, decompressedFile):
readFile = open(compressedFile, 'r').read()
decompressed = zlib.decompress(base64.b64decode(readFile))
decoded = open(decompressedFile, 'a')
decoded.write(decompressed)
decoded.close()
I saved this file as test554.py and used:
>>> import test554
>>> test554.compress("testuncompress.txt", "testuncompress2.txt")
Raw size :115
Raw size :129
>>> test554.decompress("testuncompress2.txt", "testuncompress3.txt")
This first compressed the testuncompress.txt file to testuncompress2.txt then decompressed testuncompress2.txt to testuncompress3.txt.